来自用户的帖子想知道这意味着什么:
@property (nonatomic, strong) __attribute__((NSObject)) dispatch_queue_t captureQueue;
他应该得到一些错误,我认为我会谷歌,因为我也感兴趣。
有一件事导致了另一件事,这引出了我的问题:
dispatch_queue_t
的实际类型是什么?
我也做了一些谷歌搜索,过去在SO上发现了两个问题。
一个基本上关注后缀部分,即_t
,关于POSIX和C的历史,所以它没有回答我的问题。
另一个很接近,但接受的答案基本上是说它是 typedef,没有人应该知道。它是依赖于系统的类型,必须处理位。
这不适合我作为一个好奇的人。而且我认为必须有人知道或有人比我更了解,因此我的问题在这里。
如果确实没有人知道,那么即使是一个答案,至少告诉我这个机制如何以抽象的方式工作以及如何确定其类型(BTW,运行时或编译时?)不同操作系统的不同位仍然足以让我满意。
我也只是看了queue.h
和block.m
,我发现的只是这一小段信息:
typedef struct dispatch_queue_s *dispatch_queue_t;
在queue.h
中,我看到了这一点:
__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
void dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
#endif
__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
extern struct dispatch_queue_s _dispatch_main_q;
#define dispatch_get_main_queue() (&_dispatch_main_q)
这超出了我的范围。我希望非常了解GCD的人可以分享一些关于此的知识。
答案 0 :(得分:6)
TL; DR版本:
如果您的好奇只是想知道struct dispatch_queue_s
中的字段是什么,您可以在this file中自己阅读,但作为API的使用者/用户,您永远不需要知道这一点信息以便使用它。因为你永远不需要知道,并且因为该结构中的字段不是公共API的一部分,如果你使用这些知识(除了你自己的启发和娱乐),你就是在为自己设置麻烦。
长版:
让我们看看我是否可以在这里逐一进行:
来自用户的帖子想知道这意味着什么:
@property(非原子,强)属性((NSObject)) dispatch_queue_t captureQueue;据说他得到了一些错误 我以为我会谷歌,因为我也感兴趣。
有一件事导致了另一件事,这引出了我的问题:
将
__attribute__((NSObject))
应用于不可保留的属性 对象指针类型与ARC之外的行为相同:它 要求属性类型是某种指针并允许 使用除assign之外的修饰符。这些修饰符只影响 合成吸气剂和定位剂;直接进入伊达(即使 合成的)仍然具有原始语义,以及ivar中的值 在解除分配期间不会自动释放。
由于你不能说出问题所在,所以我很难解决这些问题。我自己从不使用它,从阅读文档,听起来似乎不推荐。我当然不需要这样就可以在持有dispatch_queue_t
的属性上获得强大的ARC语义。
接下来的事情:
dispatch_queue_t的实际类型是什么?
我也做了一些谷歌搜索,过去发现了2个问题 在SO上。其中一个主要关注后缀部分,即_t 关于POSIX和C的历史,所以它没有回答我的问题。
好的,_t
后缀是"reserved namespace" that POSIX "called dibs on" way back when in POSIX.1。所有这些意味着,如果您想在类型上使用_t
的后缀,POSIX不会承诺新版本的POSIX规范也不会声明具有相同名称的类型这可能会破坏你的代码。在实践中,您可以继续使用后缀,如果您喜欢它,或者是否有助于您更好地理解代码,或者使其看起来更像POSIX-y,或者其他什么。或者不要使用它。这是你的选择。
另一个很接近,但接受的答案基本上是这样说的 是一个typedef,没有人应该知道。它是一个 依赖于系统的类型,必须处理位。
不是那个"没有人应该知道"更多的是"此API的消费者被警告不要关心" - 将指向此类型的指针视为不透明。这是typedef:
typedef struct dispatch_queue_s *dispatch_queue_t;
为了剖析这一点,这意味着dispatch_queue_t
是指向前向声明的结构dispatch_queue_s
的指针。 API的消费者不需要知道该结构的布局,因此它宣布而不是定义这一事实并不会导致编译器到barf。你可以使用你的声明可见的东西,但是它的定义并不是所有的时间(任何时候你调用库函数,如printf
或NSLog
或其他什么。)通过类比,如果我给你邮寄信件的街道地址(指针),你会认为在那个地址有一座建筑物(指向的东西),但你不需要知道建筑物是房子,还是办公楼或其他什么,如果您与它的唯一互动是通过其地址发送和接收邮件。
与_t
一样,这是一种面向未来的做法。如果您将dispatch_queue_t
(指针)视为不透明,并且Apple在将来的版本中更改struct dispatch_queue_s
的内部结构,则您的代码不会中断。你从未对它的内部做出任何假设,因为你没有这些信息。
我和一个好奇的人并不是很好。我想 必须有人知道或有人比我更了解, 因此我的问题在这里。
libdispatch
is open source,所以你几乎可以阅读所有关于它的知识。再说一次,并不是说你不应该知道"为了使用它,你不需要知道它。如果你真的想知道,那么......正如他们所说,"使用来源,卢克。"切入正题?如果您的好奇心想知道struct dispatch_queue_s
中的字段是什么,您可以在this file中自己阅读,但作为API的使用者,您将永远不需要知道此信息才能使用GCD 。 FWIW,GCD来源可能有点难以解析(很多分支预测暗示了所有地方的东西,很多#defines
等)所以阅读它可能会或可能不会真正帮助你理解你是什么&#39 ;试图理解。
如果真的没有人知道,那么即使答案也是如此 至少我是如何以一种抽象的方式运作这种机制以及它是如何运作的 根据的确定类型(BTW,运行时或编译时?) 不同操作系统的不同位仍然足以让我满意。
我希望我能够帮助解决这个问题。 FWIW,这些东西在编译时都知道各种编译时间"每个组件。当struct dispatch_queue_s
由Apple编译并随操作系统附带时,libdispatch
的布局是已知的。当你的程序编译时,它将知道它需要知道的一切,这仅限于"有一个结构,在其他地方定义,称为dispatch_queue_s
,我将与该结构进行交互使用不透明的指针。"
最后:
__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
void dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
#endif
__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
extern struct dispatch_queue_s _dispatch_main_q;
#define dispatch_get_main_queue() (&_dispatch_main_q)
在您理解不透明类型的过程中,此代码主要是一个红色的鲱鱼。第一部分是声明函数dispatch_async
,第二部分是一个小技巧,说明另一个库(extern)中有一个公共全局变量,类型为struct dispatch_queue_s
,其符号为{ {1}},只要预处理器看到字符串_dispatch_main_q
,就应该用dispatch_get_main_queue()
替换它。当人们想要获得指向主队列的指针时,这节省了函数调用的开销。它可以很容易地被声明为完全不透明的函数,如:(&_dispatch_main_q)
并在库中定义如下:
dispatch_queue_t dispatch_get_main_queue(void);
...虽然表现不佳。希望这很有用。