YYDispatchQueuePool阅读笔记
阅读了开源大神的YYDispatchQueuePool,在此记下一些从中学到的东西。
首先YYDispatchQueuePool.m文件中有如下类型对应:
static inline dispatch_queue_priority_t NSQualityOfServiceToDispatchPriority(NSQualityOfService qos) {
switch (qos) {
case NSQualityOfServiceUserInteractive: return DISPATCH_QUEUE_PRIORITY_HIGH;
case NSQualityOfServiceUserInitiated: return DISPATCH_QUEUE_PRIORITY_HIGH;
case NSQualityOfServiceUtility: return DISPATCH_QUEUE_PRIORITY_LOW;
case NSQualityOfServiceBackground: return DISPATCH_QUEUE_PRIORITY_BACKGROUND;
case NSQualityOfServiceDefault: return DISPATCH_QUEUE_PRIORITY_DEFAULT;
default: return DISPATCH_QUEUE_PRIORITY_DEFAULT;
}
}
NSQualityOfService
枚举定义了以下值:
UserInteractive
:和图形处理相关的任务,比如滚动和动画。UserInitiated
:用户请求的任务,但是不需要精确到毫秒级。例如,如果用户请求打开电子邮件App来查看邮件。Utility
:周期性的用户请求任务。比如,电子邮件App可能被设置成每五分钟自动检查新邮件。但是在系统资源极度匮乏的时候,将这个周期性的任务推迟几分钟也没有大碍。Background
:后台任务,用户可能并不会察觉对这些任务。比如,电子邮件App对邮件进行引索以方便搜索。
而对于QOS YYDispatchQueuePool也有如下对应关系:
1. NSQualityOfServiceUserInteractive -> QOS_CLASS_USER_INTERACTIVE
2. NSQualityOfServiceUserInitiated -> QOS_CLASS_USER_INITIATED
3. NSQualityOfServiceUtility -> QOS_CLASS_USER_INITIATED
4. NSQualityOfServiceBackground -> QOS_CLASS_BACKGROUND
5. NSQualityOfServiceDefault -> QOS_CLASS_DEFAULT
我们可以看出在创建线程池的时候会与GCD里面的线程Dispatch Queue产生映射关系。
接下来他定义了这样一个结构体
typedef struct {
const char *name; // 定义一个name指针,用来储存队列名称
void **queues; //定义一个queues,指向队列的内存地址
uint32_t queueCount; //队列个数
int32_t counter; //好吧,这里我也不是很清楚
} YYDispatchContext;
YYDispatchContextCreate (const char *name, uint32_t queueCount, NSQualityOfService qos); //这里类似于C++里面的构造方法,也类似于OC里面的init方法,返回YYDispatchContext对象。
static YYDispatchContext *YYDispatchContextCreate(const char *name, uint32_t queueCount, NSQualityOfService qos) { YYDispatchContext *context = calloc(1, sizeof(YYDispatchContext)); if (!context) return NULL; context->queues = calloc(queueCount, sizeof(void *)); if (!context->queues) { free(context); return NULL; } if ([UIDevice currentDevice].systemVersion.floatValue >= 8.0) { } else { long identifier = NSQualityOfServiceToDispatchPriority(qos); for (NSUInteger i = 0; i < queueCount; i++) { dispatch_queue_t queue = dispatch_queue_create(name, DISPATCH_QUEUE_SERIAL); dispatch_set_target_queue(queue, dispatch_get_global_queue(identifier, 0)); context->queues[i] = (__bridge_retained void *)(queue); } } context->queueCount = queueCount; if (name) { context->name = strdup(name); //字符串拷贝函数 } return context; }
这里首先根据队列个数开辟相应个数的内存空间,然后再将QOS状态转换成队列优先级状态。前面已经列出了对应关系。根据初始化队列个数利用dispatch_queue_create(name,DISPATCH_QUEUE_SERIAL)生成对应的线程加到串行队列里面去。最后给YYDispatchContext的结构体赋值。同理,
YYDispatchContextRelease(YYDispatchContext *context) //即为释放YYDispatchContext的方法,同样的我们来看一看源码
static void YYDispatchContextRelease(YYDispatchContext *context) { if (!context) return; if (context->queues) { for (NSUInteger i = 0; i < context->queueCount; i++) { void *queuePointer = context->queues[i]; dispatch_queue_t queue = (__bridge_transfer dispatch_queue_t)(queuePointer); const char *name = dispatch_queue_get_label(queue); if (name) strlen(name); queue = nil; } free(context->queues); context->queues = NULL; } if (context->name) free((void *)context->name); }
这里我们同样的遍历YYDispatchContext的队列,先是通过YYDispatchContext结构体的queues指针获取到dispatch_queue_t,然后对队列清空,最后利用C语言的free()函数释放内存空间。
获取队列方法如下:
static dispatch_queue_t YYDispatchContextGetQueue(YYDispatchContext *context) { int32_t counter = OSAtomicIncrement32(&context->counter); if (counter < 0) counter = -counter; void *queue = context->queues[counter % context->queueCount]; return (__bridge dispatch_queue_t)(queue); }
之前讲到counter的时候不太理解这个的含义,这里代码主要是通过context获取队列。
接着
YYDispatchContext *YYDispatchContextGetForQOS(NSQualityOfService qos) ; //此方法是根据对应的qos状态创建YYDispatchContext;
最后使用起来也是比较方便,请参考YY大神的YYDispatchQueuePool。
整个demo涵盖着对GCD的深入理解,C语言尤为重要