// dispatch_queue_set_specific 设置 key - value, 队列判断使用
IsOnSocketQueueOrTargetQueueKey = &IsOnSocketQueueOrTargetQueueKey;
void *nonNullUnusedPointer = (__bridge void *)self;
dispatch_queue_set_specific(socketQueue, IsOnSocketQueueOrTargetQueueKey, nonNullUnusedPointer, NULL);
// 判断队列,保证在特定的队列,执行任务
- (void)dealloc
{
...
if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
{
[self closeWithError:nil];
}
else
{
dispatch_sync(socketQueue, ^{
[self closeWithError:nil];
});
}
...
}
// 保证同步执行
+ (nullable instancetype)socketFromConnectedSocketFD:(int)socketFD delegate:(nullable id<GCDAsyncSocketDelegate>)aDelegate delegateQueue:(nullable dispatch_queue_t)dq socketQueue:(nullable dispatch_queue_t)sq error:(NSError* __autoreleasing *)error
{
__block BOOL errorOccured = NO;
GCDAsyncSocket *socket = [[[self class] alloc] initWithDelegate:aDelegate delegateQueue:dq socketQueue:sq];
dispatch_sync(socket->socketQueue, ^{ @autoreleasepool {
...
}});
return errorOccured? nil: socket;
}
// 保证唯一队列, 获取信息,多线程保护
- (id)delegate
{
if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
{
return delegate;
}
else
{
__block id result;
dispatch_sync(socketQueue, ^{
result = self->delegate;
});
return result;
}
}
// 多线程保护, 将执行的任务, 封装成block 块儿,提交到特定的队列上,异步,或 同步执行.
- (void)setDelegate:(id)newDelegate synchronously:(BOOL)synchronously
{
dispatch_block_t block = ^{
self->delegate = newDelegate;
};
if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey)) {
block();
}
else {
if (synchronously)
dispatch_sync(socketQueue, block);
else
dispatch_async(socketQueue, block);
}
}
// return_from_block 还是有意义的
dispatch_block_t block = ^{ @autoreleasepool {
...
// 可以定义宏,明确return 的含义
return_from_block;
}
};
dispatch_queue_set_specific, dispatch_get_specific 用来判断队列
将任务封装block,在异步,或者 同步时,执行 block
宏定义
return_from_block
来明确 return 所在的含义
block 内部,weak strong == nil 直接return
// dispatch_source_type read 读文件描述符
self->accept4Source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, self->socket4FD, 0, self->socketQueue);
// event handler
dispatch_source_set_event_handler(self->accept4Source, ^{ @autoreleasepool {
#pragma clang diagnostic push
#pragma clang diagnostic warning "-Wimplicit-retain-self"
// 很赞的,一个写法
__strong GCDAsyncSocket *strongSelf = weakSelf;
if (strongSelf == nil) return_from_block;
LogVerbose(@"event4Block");
unsigned long i = 0;
// get data 是获取可用字节的长度
unsigned long numPendingConnections = dispatch_source_get_data(acceptSource);
LogVerbose(@"numPendingConnections: %lu", numPendingConnections);
// 执行读取 socket 字节数
while ([strongSelf doAccept:socketFD] && (++i < numPendingConnections));
#pragma clang diagnostic pop
}});
// cancel_hander
dispatch_source_set_cancel_handler(self->accept4Source, ^{
#pragma clang diagnostic push
#pragma clang diagnostic warning "-Wimplicit-retain-self"
#if !OS_OBJECT_USE_OBJC
LogVerbose(@"dispatch_release(accept4Source)");
dispatch_release(acceptSource);
#endif
LogVerbose(@"close(socket4FD)");
close(socketFD);
#pragma clang diagnostic pop
});
// 开始准备读数据
dispatch_resume(self->accept4Source);
// cancel source
dispatch_source_cancel(accept4Source);
// dispatch_after 延时执行任务
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(alternateAddressDelay * NSEC_PER_SEC)), socketQueue, ^{
[self connectSocket:alternateSocketFD address:alternateAddress stateIndex:aStateIndex];
});
// source timer
connectTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, socketQueue);
// timer handler
dispatch_source_set_event_handler(connectTimer, ^{ @autoreleasepool {
#pragma clang diagnostic push
#pragma clang diagnostic warning "-Wimplicit-retain-self"
__strong GCDAsyncSocket *strongSelf = weakSelf;
if (strongSelf == nil) return_from_block;
[strongSelf doConnectTimeout];
#pragma clang diagnostic pop
}});
dispatch_time_t tt = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(timeout * NSEC_PER_SEC));
dispatch_source_set_timer(connectTimer, tt, DISPATCH_TIME_FOREVER, 0);
dispatch_resume(connectTimer);
// cancel timer
if (connectTimer)
{
dispatch_source_cancel(connectTimer);
connectTimer = NULL;
}
// read source
readSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, socketFD, 0, socketQueue);
// 挂起暂停
dispatch_suspend(readSource);
// 继续执行任务
dispatch_resume(readSource);
// write source
writeSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_WRITE, socketFD, 0, socketQueue);
dispatch_source DISPATCH_SOURCE_TYPE_READ ,一般读文件,读流等
cancel_hander 关闭时,关闭正在打开的文件.
event_handler 用来接收事件,
dispatch_source_get_data 获取,获取到的字节数.
dispatch_after 延迟执行任务
在设置 read 的 event hander时, 读文件内容,或者 ,读socket 流的内容
网友评论