Objective-C 线程篇(三): GCD的实现

2018-11-10  本文已影响122人  Tenloy

GCD (Grand Central Dispatch),在系统级即iOS和OS X的核心XNU内核级上实现,所以开发者无论如何努力编写线程关系代码,性能都不可能胜过XNU内核级所实现的GCD。

Dispatch Queue实现

# Dispatch Quene实现的所需

# 用于实现Dispatch Queue的几个软件组件框架

# 执行上下文

Dispatch Quene通过结构体和链表,被实现为FIFO队列。

Block并不是直接加入FIFO队列,而是先加入Dispatch Continuation这一dispatch_continuation_t类型结构体中,然后再加入FIFO队列。该Dispatch Continuation用于记忆Block所属的Dispatch Group和其他一些信息,相当于一般常说的执行上下文

上一篇在将Global Dispatch Queue的时候,我们介绍过8种类型,这8种Global Dispatch Quene各使用一个pthread_workquene。

GCD初始化时,使用pthread_workquene_creat_np函数生成"pthread_workquene"
pthread_workquene包含在Libc提供的pthreads API 中。
其使用bsdthread_register和workq_open系统调用,"在初始化XNU内核的workquene之后获取workquene信息"

XNU内核持有4种workquene:
WORKQUENE_HIGH_PRIOQUENE
WORKQUENE_Default_PRIOQUENE
WORKQUENE_Low_PRIOQUENE
WORKQUENE_BG_PRIOQUENE

优先级与Global Dispatch Quene的四种执行优先级相同。

Global Dispatch Queue --> Libc pthread_wordqueue --> XNU workqueue

网图 侵删

# Dispatch Queue执行Block的过程

Dispatch Source

GCD中除了主要的Dispatch Queue外,还有不太引人注目的Dispatch Source。它是BSD系内核惯有功能kqueue的包装

kqueue是XNU内核中发生各种事件时,在应用程序编程方执行处理的技术。其CPU负荷非常小,尽量不占用资源。kqueue可以说是应用程序处理XNU内核中发生的各种事件的方法中最优秀的一种。

Dispatch Source可处理以下事件:

DISPATCH_SOURCE_TYPE_DATA_ADD   变量增加
DISPATCH_SOURCE_TYPE_DATA_OR    变量OR
DISPATCH_SOURCE_TYPE_MACH_SEND  MACH端口发送
DISPATCH_SOURCE_TYPE_MACH_RECV  MACH端口接收
DISPATCH_SOURCE_TYPE_PROC   检测到与进程相关的事件
DISPATCH_SOURCE_TYPE_READ   可读取文件映像
DISPATCH_SOURCE_TYPE_SIGNAL 接收信号
DISPATCH_SOURCE_TYPE_TIMER  定时器
DISPATCH_SOURCE_TYPE_VNODE  文件系统有变更
DISPATCH_SOURCE_TYPE_WRITE  可写入文件映像

事件发生时,在指定的Dispatch Queue中可执行事件的处理。


    dispatch_queue_t queue = dispatc_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    /*
     *  基于READ事件作成Dispatch Source
     */  
    dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, sockfd, 0 , queuq);

    /* 指定发生READ事件时执行的处理 */    
    dispatch_source_set_event_handler(source, ^{
        // 处理结束,取消Dispatch Source
        dispatch_source_cancel(source);
    });

    /* 指定取消Dispatch Source时的处理 */
    dispatch_source_set_cancel_handler(source, ^{
        /* 释放Dispatch Source(自身) */
        dispatch_release(source);
    });

    /* 启动Dispatch Source */
    dispatch_resume(source);

与上面代码非常相似的代码,使用在了Core Foundation框架的用于异步网络的API CFSocket中。因为Foundation框架的异步网络API是通过CFSocket实现的,所以可享受到仅使用Foundation框架的Dispatch Source(即GCD)带来的好处。

一旦将任务追加到Dispatch Queue中,就没有办法将任务取消,也没有办法在执行中取消任务。Dispatch Source是可以取消的,而且取消时的处理可以block的形式作为参数配置。在必须使用kqueue的情况下,推荐大家使用Dispatch Source,比较简单

上一篇 下一篇

猜你喜欢

热点阅读