• usr/include/dispatch


    博文一部分摘自:Parse分析,以下简称博文1(LeanCloud工程师针对Parse使用GCD的分析)
    博文一部分摘自:GCD入门,以下简称博文2
    建议先了解一下:BSD基础知识

    Dispatch/source.h中是这样描述Dispatch Source####

    The dispatch framework provides a suite of Interfaces for monitoring low-level system objects (file descriptions , Mach Ports , signals , VFS nodes , etc.) 
    for activity and automatically submitting event handler blocks to dispatch queues when such activity occurs.
    
    The suite of interfaces is known as the Dispatch Source API
    
    abstract:
    Dispatch Source are used to automatically submit event handler blocks to dispatch queues in response to external events.
    

    简单来说####

    Dispatch Source 是用来监听某些类型事件的对象,当这些事件发生时,Dispatch Source 自动把事件block放入到Dispatch queue的执行例程中。

    Dispatch Source 监听的底层事件####

    下面是GCD 10.6.0 版本支持的事件:

    • Mach port send right state changes.
    • Mach port receive right state changes.
    • External process state changes.
    • File descriptor ready for read.
    • File descriptor ready for write.
    • File system node event.
    • POSIX signal.
    • Custom timer.
    • Custom event.

    这些事件支持所有kqueue支持的事件、mach端口、内建计时器支持(这样我们就不用使用timeout参数来创建自己的计时器)和用户事件。

    如果对这些知识点不了解,可以看我对知识点的整理 - 知识点资料 3 ~ 6

    一、 Custom event

    博文1中说Dispatch Source比使用dispatch_async的优势在于利用合并

    合并:在任一thread调用它的一个函数dispatch_source_merge_data后,会执行Dispatch Source事先定义好的event handler(博主1认为是block)。

    博文以总结说,联结的这个过程就称为 - Custom event(用户事件)。是dispatch source支持处理的一种事件。简单说,这种事件是由你调用dispatch_source_merge_data函数来向自己发送信号。

    1.1 Dispatch Source 的使用步骤 详情介绍点 - 这里###

    • 创建一个 Dispatch Source
    • 创建 Dispatch Source 的事件句柄
    • 处理 Dispatch Source 的resume() 和 suspend() 操作。
    • 向 Dispatch Source 发送事件。

    1.1.1 创建一个 Dispatch Source

        dispatch_source_create(<#dispatch_source_type_t type#>,
                               <#uintptr_t handle#>,
                               <#unsigned long mask#>,
                               <#dispatch_queue_t queue#>);
        /** 参数1
         *  dispatch_source_type_t type
         *  需要监听的事件类型
         */
        /** 参数2
         *  uintptr_t handle 
         *  理解为 id、索引或句柄。假如要监听process,需要传入process的pId.
         */
        /** 参数3
         *  unsigned long mask
         *  根据参数2,理解为description、provide或detail description,让source知道具体要监听什么。
         */
        /** 参数4
         *  dispatch_queue_t queue
         *  当监听事件发生,将event_handle_block添加到这个queue来执行。
         */
    

    dispatch_source_type_t type

        DISPATCH_SOURCE_TYPE_DATA_ADD;   //*> custom event, 自己定义事件,自己触发事件
        DISPATCH_SOURCE_TYPE_DATA_OR;    //*> custom event, 自己定义事件,自己触发事件
        DISPATCH_SOURCE_TYPE_MACH_SEND;  //*> Mach 相关‘发送’事件
        DISPATCH_SOURCE_TYPE_MACH_RECV;  //*> Mach 相关‘接收’事件
        DISPATCH_SOURCE_TYPE_READ;       //*> I/O 操作,对文件、socket操作的‘读’响应
        DISPATCH_SOURCE_TYPE_WRITE;      //*> I/O 操作,对文件、socket操纵的‘写’响应
        DISPATCH_SOURCE_TYPE_VNODE;      //*> 文件状态监听,文件被删除、移动、重命名
        DISPATCH_SOURCE_TYPE_PROC;       //*> 进程监听,如,进程的退出、创建1或多个进程、进程收到Unix信号
        DISPATCH_SOURCE_TYPE_TIMER;      //*> 定时响应
        DISPATCH_SOURCE_TYPE_SIGNAL;     //*> 接收Unix信号时的响应
    

    创建一个dispatch_source_t source

    dispatch_source_t customSourceMonitor = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0, dispatch_get_main_queue());
    

    1.1.2 创建Dispatch_source_t 的event_handler_block###

        /**
         *  如果dispatch_source的监听类型:
         *  1.DISPATCH_SOURCE_TYPE_DATA_ADD
         *  2.DISPATCH_SOURCE_TYPE_DATA_OR
         *  这是Custom Event,自定定义Handler_Block,自己去触发Handler_Block
         */
        dispatch_source_set_event_handler(customSourceMonitor, ^{
           
            // TODO
            
        });
    

    1.1.3 处理 Dispatch_source_t 的suspend 、 resume 操作。

    初始化创建的Dispatch Source 默认是suspend。需要resume

        dispatch_resume(customSourceMonitor);
        dispatch_suspend(customSourceMonitor);
    

    1.14 向 Dispatch_Source_t 发送事件

    (下文2.1 详解)
    resume Dispatch_Source_t 之后,可以通过 dispatch_source_merge_data 向 Dispatch_Source 发送event。

    • 当dispatch_source_merge_data触发了handler_event 之后,dispatch_source_get_data(Dispatch_source_t source)就会自动清空成‘0’。

    1.15 Custom Event 演示代码

        dispatch_source_t customSourceMonitor = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0, dispatch_get_main_queue());
        dispatch_resume(customSourceMonitor);
        
        __block int sum = 0;
        dispatch_source_set_event_handler(customSourceMonitor, ^{
           
            // ?TODO
            sum += dispatch_source_get_data(customSourceMonitor);
            NSLog(@"- %d",sum);
            
        });
        //4950
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        for (NSUInteger i = 0; i < 1000; i ++) {
            dispatch_async(queue, ^{
                dispatch_source_merge_data(customSourceMonitor, i);
                
                usleep(20000); // 注释效果不同
            });
        }
    

    二、如何使用Dispatch Source 达到 NSOperationQueue 的功能

    2.1 Dispatch Source 如何通过merge的方式确保在高负载下正常工作

    1.14 中通过调用dispatch_source_merge_data后所触发dispatch_source_set_event_handler的根据merge特性调用的频率会大大减少,有时候只调用一次handler。

    为什么Dispatch Source 能通过 merge 方式确保在高负载下正常运行呢?

    在同一时间,只有一个处理block的实例被分配,如果这个handler_block还没有执行完毕,另一个事件就发生了,事件会以指定的方式 (ADD 或 OR) 进行积累。

    Dispatch Source 能通过merge事件确保在高负载下正常工作。当handler_event被执行的时,可以通过dispatch_source_get_data() 来获取计算后累加的数据。然后这个dispatch_source_get_data() 会被重置为‘0’。

    2.2 Dispatch Source 与 Dispatch Queue 两者在线程执行上的关系

    答: 没有关系

  • 相关阅读:
    操作权限和数据权限
    maven scope
    maven dependencies与dependencyManagement的区别
    maven pom继承与聚合
    java @SuppressWarnings注解
    java使用省略号代替多参数(参数类型... 参数名)
    Bean Validation 技术规范特性概述
    synchronized锁住的是代码还是对象
    Java泛型
    Java的外部类为什么不能使用private、protected进行修饰
  • 原文地址:https://www.cnblogs.com/R0SS/p/5474253.html
Copyright © 2020-2023  润新知