美文网首页
dispatch source.h

dispatch source.h

作者: 想聽丿伱說衹愛我 | 来源:发表于2020-07-28 15:40 被阅读0次

    版本:iOS13.5

    source.h

    dispatch其他文件通道

    注意:若有时handler不执行,是因为source被释放了,可以在回调中调用(void)dispatch_source_get_data(source);或设为属性@property (nonatomic, strong) dispatch_source_t *source;

    索引

    • 创建一个新的调度源以监视低级系统对象,并响应事件自动将block回调提交给队列queue。
      dispatch_source_create
    • 为调度源source设置回调handler
      dispatch_source_set_event_handler
    • 为调度源source设置函数handler
      dispatch_source_set_event_handler_f
    • 为调度源source设置取消时调用的回调handler。
      dispatch_source_set_cancel_handler
    • 为调度源source设置取消时调用的函数handler。
      dispatch_source_set_cancel_handler_f
    • 异步取消调度源,以防止调用handler。
      dispatch_source_cancel
    • 返回与此调度源source关联的handle。
      dispatch_source_get_handle
    • 返回与此调度源source关联的mask。
      dispatch_source_get_mask
    • 返回调度源source的待处理数据
      dispatch_source_get_data
    • 将数据合并到调度源source中,并将handler提交到目标队列queue再执行。
      dispatch_source_merge_data
    • 设置计时器源的开始时间,间隔和回程值。
      dispatch_source_set_timer
    • 为调度源source设置激活后就调用的回调handler
      dispatch_source_set_registration_handler
    • 为调度源source设置激活后就调用的函数handler
      dispatch_source_set_registration_handler_f

    详解

    • 创建一个新的调度源以监视低级系统对象,并响应事件自动将block回调提交给队列queue。
    dispatch_source_t dispatch_source_create(dispatch_source_type_t type, 
          uintptr_t handle, unsigned long mask, dispatch_queue_t _Nullable queue);
    

    该block回调通过dispatch_source_set_event_handlerdispatch_source_set_event_handler_f创建。
    调度源创建后是非活跃的,设置好属性(handler, context)后需要调用dispatch_activatedispatch_resume激活后才能响应事件。激活后就不能再调用dispatch_set_target_queuedispatch_activate
    type 调度源的类型
    handle mask 通过type来确定相应作用
    queue 将block提交到的调度队列。如果队列为DISPATCH_TARGET_QUEUE_DEFAULT,则源将block提交到默认优先级全局队列

    //一个调度源,它合并​​调用dispatch_source_merge_data获得的数据,通过新增来合并数据。
    //handle未使用(传0),mask未使用(传0)。
    DISPATCH_SOURCE_TYPE_DATA_ADD 
    //一个调度源,它合并​​调用dispatch_source_merge_data获得的数据,通过按位或来合并数据。
    //handle未使用(传0),mask未使用(传0)。
    DISPATCH_SOURCE_TYPE_DATA_OR
    //一个调度源,它跟踪调用dispatch_source_merge_data获得的数据。
    //新获得的数据值将替换尚未传递给源回调的现有数据值。数据值为0将导致不调用回调。
    //handle未使用(传0),mask未使用(传0)。
    DISPATCH_SOURCE_TYPE_DATA_REPLACE
    //一个调度源,它为死名通知监视Mach端口(dead name notifications 只能发送不能接收的通知)
    //handle 具有发送或只能发送一次(mach_port_t)的Mach端口
    //mask dispatch_source_mach_send_flags_t类型 见下面
    DISPATCH_SOURCE_TYPE_MACH_SEND
    //一个调度源,它为未处理消息监视Mach端口。
    //handle 具有接收权限(mach_port_t)的Mach端口
    //mask dispatch_source_mach_recv_flags_t类型 见下面 但当前未定义宏(传0)
    DISPATCH_SOURCE_TYPE_MACH_RECV
    //一个调度源,它为内存压力状况变化监视系统
    //handle未使用(传0)
    //mask dispatch_source_memorypressure_flags_t类型  见下面
    DISPATCH_SOURCE_TYPE_MEMORYPRESSURE
    //一个调度源,它为dispatch_source_proc_flags_t定义的事件监视外部进程
    //handle 进程标识符(pid_t)
    //mask dispatch_source_proc_flags_t类型 见下面
    DISPATCH_SOURCE_TYPE_PROC
    //一个调度源,它为可供读取的未处理字节监视文件描述符。
    //handle 文件描述符(int)
    //mask未使用(传0)
    DISPATCH_SOURCE_TYPE_READ
    //一个调度源,它为信号监视当前进程
    //handle 信号编号(int)
    //mask未使用(传0)
    DISPATCH_SOURCE_TYPE_SIGNAL
    //一个调度源,它基于计时器提交事件处理块
    //handle未使用(传0)
    //mask dispatch_source_timer_flags_t类型 见下面
    DISPATCH_SOURCE_TYPE_TIMER
    //一个调度源,它为由dispatch_source_vnode_flags_t定义的事件监视文件描述符
    //handle 文件描述符(int)
    //mask dispatch_source_vnode_flags_t类型 见下面
    DISPATCH_SOURCE_TYPE_VNODE
    //一个调度源,它为可用缓冲区空间去写入字节而监视文件描述符
    //handle 文件描述符(int)
    //mask未使用(传0)
    DISPATCH_SOURCE_TYPE_WRITE
    

    //破坏与发送权限相对应的接收权限
    #define DISPATCH_MACH_SEND_DEAD 0x1
    dispatch_source_mach_send_flags_t

    //暂无定义的宏
    dispatch_source_mach_recv_flags_t

    //系统内存压力状况已恢复正常
    #define DISPATCH_MEMORYPRESSURE_NORMAL 0x01
    //系统内存压力状况已更改为警告。
    #define DISPATCH_MEMORYPRESSURE_WARN 0x02
    //系统内存压力状况已变为严重。
    #define DISPATCH_MEMORYPRESSURE_CRITICAL 0x04
    dispatch_source_memorypressure_flags_t

    //该进程已经退出
    #define DISPATCH_PROC_EXIT 0x80000000
    //该进程已创建一个或多个子进程
    #define DISPATCH_PROC_FORK 0x40000000
    //通过exec()或posix_spawn(),该进程已成为另一个可执行映像。
    #define DISPATCH_PROC_EXEC 0x20000000
    //Unix信号已传递到该进程。
    #define DISPATCH_PROC_SIGNAL 0x08000000
    dispatch_source_proc_flags_t

    //系统应尽最大努力严格遵守通过dispatch_source_set_timer为计时器指定的回程值leeway
    #define DISPATCH_TIMER_STRICT 0x1
    dispatch_source_timer_flags_t;

    //文件系统对象已从namespace中删除
    #define DISPATCH_VNODE_DELETE 0x1
    //文件系统对象数据已更改。
    #define DISPATCH_VNODE_WRITE 0x2
    //文件系统对象的大小已更改。
    #define DISPATCH_VNODE_EXTEND 0x4
    //文件系统对象元数据已更改
    #define DISPATCH_VNODE_ATTRIB 0x8
    //文件系统对象链接计数已更改。
    #define DISPATCH_VNODE_LINK 0x10
    //文件系统对象在namespace中被重命名。
    #define DISPATCH_VNODE_RENAME 0x20
    //文件系统对象被吊销
    #define DISPATCH_VNODE_REVOKE 0x40
    //文件系统对象已解锁。
    #define DISPATCH_VNODE_FUNLOCK 0x100
    dispatch_source_vnode_flags_t

    例:
        dispatch_queue_t queue = dispatch_queue_create("source", DISPATCH_QUEUE_SERIAL);
        dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    
    • 为调度源source设置回调handler
    void dispatch_source_set_event_handler(dispatch_source_t source,
        dispatch_block_t _Nullable handler);
    

    handler 提交给队列queue的回调typedef void (^dispatch_block_t)(void);

    例:
        dispatch_queue_t queue = dispatch_queue_create("source", DISPATCH_QUEUE_SERIAL);
        dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
        dispatch_source_set_event_handler(timer, ^{
            NSLog(@"11");
        });
    
    • 为调度源source设置函数handler
    void dispatch_source_set_event_handler_f(dispatch_source_t source,
        dispatch_function_t _Nullable handler);
    

    handler 提交给队列queue的函数typedef void (*dispatch_function_t)(void *_Nullable);
    函数handler要传递的参数通过dispatch_set_context设置

    例:
        dispatch_queue_t queue = dispatch_queue_create("source", DISPATCH_QUEUE_SERIAL);
        dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
        dispatch_source_set_event_handler_f(timer, handler);
    
    void handler(void *context) {
        NSLog(@"22");
    }
    
    • 为调度源source设置取消时调用的回调handler。
    void dispatch_source_set_cancel_handler(dispatch_source_t source,
        dispatch_block_t _Nullable handler);
    

    handler 要提交到队列queue的回调

    例:
        dispatch_queue_t queue = dispatch_queue_create("source", DISPATCH_QUEUE_SERIAL);
        dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
        dispatch_block_t block = dispatch_block_create(DISPATCH_BLOCK_BARRIER, ^{
            NSLog(@"取消时的block");
        });
        dispatch_source_set_cancel_handler(timer, block);
    
    • 为调度源source设置取消时调用的函数handler。
    void dispatch_source_set_cancel_handler_f(dispatch_source_t source,
        dispatch_function_t _Nullable handler);
    

    handler 要提交到队列queue的函数
    函数handler要传递的参数通过dispatch_set_context设置

        dispatch_queue_t queue = dispatch_queue_create("source", DISPATCH_QUEUE_SERIAL);
        dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
        dispatch_source_set_cancel_handler_f(timer, handler);
    
    void handler(void *context) {
        NSLog(@"22");
    }
    
    • 异步取消调度源,以防止调用handler。
    void dispatch_source_cancel(dispatch_source_t source);
    

    不会取消正在运行的handler

    • 测试调度源source是否已取消。
    long dispatch_source_testcancel(dispatch_source_t source);
    

    long 如果取消,则返回非0;如果未取消,则返回0。

    例:
        dispatch_queue_t queue = dispatch_queue_create("source", DISPATCH_QUEUE_SERIAL);
        dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
        dispatch_source_set_event_handler(timer, ^{
            NSLog(@"11");
        });    
        //因为创建的timer是未激活的 需要先激活才能操作
        dispatch_activate(timer);
        dispatch_source_cancel(timer);
        long result = dispatch_source_testcancel(timer);
        NSLog(@"%ld", result);
    输出:
    1
    
    • 返回与此调度源source关联的handle。
    uintptr_t dispatch_source_get_handle(dispatch_source_t source);
    

    handle为dispatch_source_create中传入的handle

    • 返回与此调度源source关联的mask。
    unsigned long dispatch_source_get_mask(dispatch_source_t source);
    

    mask为dispatch_source_create中传入的mask

    例:
        dispatch_queue_t queue = dispatch_queue_create("source", DISPATCH_QUEUE_SERIAL);
        dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 1, 2, queue);
        dispatch_source_set_event_handler(timer, ^{
            NSLog(@"11");
        });
        //因为创建的timer是未激活的 需要先激活才能操作
        dispatch_activate(timer);    
        long handle = dispatch_source_get_handle(timer);
        long mask = dispatch_source_get_mask(timer);
        NSLog(@"%ld %ld", handle, mask);
    输出:
    1 2
    
    • 返回调度源source的待处理数据
    unsigned long dispatch_source_get_data(dispatch_source_t source);
    

    该函数应在handler中调用。在handler之外调用此函数的结果是不确定的。
    long 返回的结果根据dispatch_source_create传入的type而不同

     *  DISPATCH_SOURCE_TYPE_DATA_ADD:        应用定义的数据
     *  DISPATCH_SOURCE_TYPE_DATA_OR:         应用定义的数据
     *  DISPATCH_SOURCE_TYPE_DATA_REPLACE:    应用定义的数据
     *  DISPATCH_SOURCE_TYPE_MACH_SEND:       dispatch_source_mach_send_flags_t
     *  DISPATCH_SOURCE_TYPE_MACH_RECV:       dispatch_source_mach_recv_flags_t
     *  DISPATCH_SOURCE_TYPE_MEMORYPRESSURE   dispatch_source_memorypressure_flags_t
     *  DISPATCH_SOURCE_TYPE_PROC:            dispatch_source_proc_flags_t
     *  DISPATCH_SOURCE_TYPE_READ:            可读取的估计字节数
     *  DISPATCH_SOURCE_TYPE_SIGNAL:          自handler调用以来传递的信号数
     *  DISPATCH_SOURCE_TYPE_TIMER:           自handler调用以来计时器已触发的次数
     *  DISPATCH_SOURCE_TYPE_VNODE:           dispatch_source_vnode_flags_t
     *  DISPATCH_SOURCE_TYPE_WRITE:           估计可用缓冲区空间
    
    • 将数据合并到调度源source中,并将handler提交到目标队列queue再执行。
    void dispatch_source_merge_data(dispatch_source_t source, unsigned long value);
    

    该方法只支持dispatch_source_create的 type为DISPATCH_SOURCE_TYPE_DATA_ADDDISPATCH_SOURCE_TYPE_DATA_ORDISPATCH_SOURCE_TYPE_DATA_REPLACE的源
    value 与待处理数据合并的值。传0时无效,也不会将handler提交到目标队列queue执行。

    例:
        dispatch_queue_t queue = dispatch_queue_create("source", DISPATCH_QUEUE_SERIAL);
        dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0, queue);
        dispatch_source_set_event_handler(source, ^{
            NSLog(@"source");
            long data = dispatch_source_get_data(source);
            NSLog(@"%ld", data);
        });
        dispatch_source_merge_data(source, 100);
        dispatch_source_merge_data(source, 200);
        dispatch_activate(source);
    输出:
    source
    300
    
    • 设置计时器源的开始时间,间隔和回程值。
    void dispatch_source_set_timer(dispatch_source_t source, dispatch_time_t start,
                    uint64_t interval,uint64_t leeway);
    

    该方法只支持dispatch_source_create的 type为DISPATCH_SOURCE_TYPE_TIMER的源
    该方法会清除先前的计时器累积的所有未处理源数据。
    如果定时器源已被取消,则调用此方法无效。
    start 计时器下一次触发的时间
    interval 每次触发的间隔 设为DISPATCH_TIME_FOREVER表示只会调用一次
    leeway 系统可能会延迟计时器的启动时间,以提高功耗和系统性能。允许延迟的上限可以用leeway参数配置,下限则由系统控制。
    如果指定的计时器源是使用DISPATCH_TIMER_STRICT的mask创建的,则系统将尽最大努力严格遵守所提供的leeway值,即使该值小于当前下限

    例:
        dispatch_queue_t queue = dispatch_queue_create("source", DISPATCH_QUEUE_SERIAL);
        dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, DISPATCH_TIMER_STRICT, queue);
        dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC, 1 * NSEC_PER_SEC);
        dispatch_source_set_event_handler(timer, ^{
            (void)dispatch_source_get_data(timer);
            NSLog(@"timer");
        });
        dispatch_resume(timer);
    输出:
    timer
    timer
    ...
    
    • 为调度源source设置激活后就调用的回调handler
    void dispatch_source_set_registration_handler(dispatch_source_t source,
        dispatch_block_t _Nullable handler);
    

    如果在dispatch_resumedispatch_activate之后调用该方法,那么handler将直接被提交到源的目标队列queue并执行
    handler 提交到源的目标队列的回调

    例:
        dispatch_queue_t queue = dispatch_queue_create("source", DISPATCH_QUEUE_SERIAL);
        dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0, queue);
        dispatch_source_set_registration_handler(source, ^{
            NSLog(@"激活后回调");
        });
        dispatch_resume(source);
    输出:
    激活后回调
    
    • 为调度源source设置激活后就调用的函数handler
    void dispatch_source_set_registration_handler_f(dispatch_source_t source,
        dispatch_function_t _Nullable handler);
    

    handler 提交到源的目标队列的函数
    函数handler要传递的参数通过dispatch_set_context设置

    用法

    用法1:
        dispatch_queue_t queue = dispatch_queue_create("source", DISPATCH_QUEUE_SERIAL);
        dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0, queue);
        dispatch_source_set_event_handler(source,^{
            (void)dispatch_source_get_data(source);
            NSLog(@"操作一次");
        });
        dispatch_resume(source);
        //调用后会执行一次回调
        dispatch_source_merge_data(source, 1);
    输出:
    操作一次
    用法2:
        dispatch_queue_t queue = dispatch_queue_create("source", DISPATCH_QUEUE_SERIAL);
        dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0, queue);
        dispatch_source_set_event_handler(source,^{
            long data = dispatch_source_get_data(source);
            NSLog(@"操作一次 %ld", data);
        });
        dispatch_resume(source);
        dispatch_async(dispatch_get_main_queue(), ^{
            for (NSInteger i = 1; i < 5; i++) {
                dispatch_source_merge_data(source, i);
    //            [NSThread sleepForTimeInterval:0.1];
            }
        });
    输出: 虽然执行了4次dispatch_source_merge_data,但会将data相加后只执行一次回调handler
    操作一次 10
    若取消注释[NSThread sleepForTimeInterval:0.1]
    输出:则会执行多次block
    操作一次 1
    操作一次 2
    操作一次 3
    操作一次 4
    用法3:
        __block NSInteger timeout = 5;
        dispatch_queue_t queue = dispatch_queue_create("source", DISPATCH_QUEUE_SERIAL);
        dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, DISPATCH_TIMER_STRICT, queue);
        dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
        dispatch_source_set_event_handler(timer, ^{
            (void)dispatch_source_get_data(timer);
            if (timeout > 0) {
                NSLog(@"倒计时%ld秒", timeout);
                timeout--;
            } else {
                NSLog(@"倒计时结束");
                dispatch_source_cancel(timer);
            }
        });
        dispatch_activate(timer);
    输出:
    倒计时5秒
    倒计时4秒
    倒计时3秒
    倒计时2秒
    倒计时1秒
    倒计时结束
    

    相关文章

      网友评论

          本文标题:dispatch source.h

          本文链接:https://www.haomeiwen.com/subject/iwialktx.html