博文一部分摘自: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 两者在线程执行上的关系

答: 没有关系

usr/include/dispatch - dispatch_source的更多相关文章

  1. /usr/include/sys/types.h:62: error: conflicting types for ‘dev_t’

    /usr/include/sys/types.h:62: error: conflicting types for ‘dev_t’/usr/include/linux/types.h:13: erro ...

  2. 解决Cannot find MySQL header files under /usr/include/mysql的错误

    按照下面的步骤能成功,亲测.转帖,做笔记 编译php-5.5-6的mysql支持,出现Cannot find MySQL header files under /usr/include/mysql. ...

  3. 编译安装php Cannot find MySQL header files under /usr/include/mysql.

    编译php-5.5-6的mysql支持,出现Cannot find MySQL header files under /usr/include/mysql. Note that the MySQL c ...

  4. error: /usr/include/objc/objc-class.h: No such file or directory

    When i use the example of ShareKit package,i have come across this error:"error: /usr/include/o ...

  5. error: /usr/include/stdio.h: Permission denied 的一种情况分析

    error: /usr/include/stdio.h: Permission denied 的一种情况分析 代码: #include <stdio.h> int main(){ prin ...

  6. Mac下一个/usr/include失踪

    Mac升级到Yosemite后,突然发现vim的YouCompleteMe代码提示所以空头支票成员,排查了一下,原本/usr/include目录中缺少.所有的C/C++头文件不见了. .. 第一次发现 ...

  7. ubuntu没有/usr/include/sys目录

    实际上不是没有sys目录,只是系统给换路径了 32位系统:/usr/incude/i386-linux-gnu/sys 64位系统:/usr/include/x86_64-linux-gnu/sys/ ...

  8. [C++]Linux之头文件sys/types.h[/usr/include/sys]

    1.查找<sys/types.h>文件 一般地,Linux的C头文件<sys/types.h>路径在如题的途径:/usr/include/sys下,然而博主[Linux For ...

  9. usr/include/c++/6.4.1/bits/stl_relops.:67: Parse error at "std"

    问题描述: 1.编译某qt工程的32位架构二进制包时,出现了上面错误,具体错误信息如下 qmake-qt5 -o ProductLicense/Makefile ProductLicense/Prod ...

随机推荐

  1. 一道常被人轻视的前端JS面试题

    前言 年前刚刚离职了,分享下我曾经出过的一道面试题,此题是我出的一套前端面试题中的最后一题,用来考核面试者的JavaScript的综合能力,很可惜到目前为止的将近两年中,几乎没有人能够完全答对,并非多 ...

  2. 特定IP访问远程桌面

    1. 新建IP安全策略 (远程端口没有修改情况下的设置) WIN+R打开运行对话框,输入“gpedit.msc”进入组策略编辑器. 依次打开:本地计算机策略--计算机配置--Windows设置--安全 ...

  3. SQL Server 2008 安装过程中遇到“性能计数器注册表配置单元一致性”检查失败 问题的解决方法

    操作步骤: 1. 在 Microsoft Windows 2003 或 Windows XP 桌面上,依次单击"开始"."运行",然后在"打开&quo ...

  4. 把Tomcat注册为windows服务

    配置环境变量 JAVA_HOME=D:\java CLASSPATH=.;%JAVA_HOME%\lib; PATH=%JAVA_HOME%\bin; 提示:一般jre默认在jdk目录下%JAVA_H ...

  5. Centos 安装jdk1.8

    我是根据右边链接进行安装的 ,但是第一步不同噢.http://www.cnblogs.com/spiders/archive/2016/09/06/5845727.html 1.下载rpm安装文件. ...

  6. RHEL7.2和RHEL6.5的配置网络yum源和本地yum源

    RHEL7.2配置本地yum源 [root@localhost ~]#monut /dev/sr0 /mnt      #挂载光盘 [root@localhost ~]# rm -rf /etc/yu ...

  7. jQuery 3.0的buildFragment

    在 jQuery3.0中,buildFragment 是一个私有函数,用来构建一个包含子节点 fragment 对象.这个 fragment 在 DOM1 中就已经有了,所有浏览器都支持.当频繁操作( ...

  8. PHP开发环境搭建

    链接: Q&A1.Mac下的PHP环境搭建 Mac 下如何搭建 PHP 开发环境? [PHP] Mac下homebrew安装及php.mysql.nginx环境安装及配置个人PHP开发环境的选 ...

  9. C#.NET 大型企业信息化系统集成快速开发平台 4.1 版本 - 面向数据库SQL语句的应用开发二

    很多传统企业.包括系统集成类的IT企业,若不是从事专业软件开发领域的,能做出一套适合本公司企业信息化的灵活的信息系统还是很有难度的,还有一些已经多年不写程序的资深开发人员,初学者,都难把一个整套系统实 ...

  10. 在Windows Server 2012 R2上安装SharePoint 2013 with SP1失败,提示没有.net4.5的解决办法

    现在的Server用Windows Server 2012 R2的越来越多了,在部署带Sp1的SharePoint2013的时候,走完预安装工具后,点击setup提示缺少.net4.5. 其实Wind ...