GCD:dispatch_queue_t的类型(dispatch_queue_s *)

时间:2014-02-05 06:03:49

标签: grand-central-dispatch

来自用户的帖子想知道这意味着什么:

@property (nonatomic, strong) __attribute__((NSObject)) dispatch_queue_t captureQueue;

他应该得到一些错误,我认为我会谷歌,因为我也感兴趣。

有一件事导致了另一件事,这引出了我的问题:

dispatch_queue_t的实际类型是什么?

我也做了一些谷歌搜索,过去在SO上发现了两个问题。 一个基本上关注后缀部分,即_t,关于POSIX和C的历史,所以它没有回答我的问题。

另一个很接近,但接受的答案基本上是说它是 typedef,没有人应该知道。它是依赖于系统的类型,必须处理位

这不适合我作为一个好奇的人。而且我认为必须有人知道或有人比我更了解,因此我的问题在这里。


如果确实没有人知道,那么即使是一个答案,至少告诉我这个机制如何以抽象的方式工作以及如何确定其类型(BTW,运行时或编译时?)不同操作系统的不同位仍然足以让我满意。


我也只是看了queue.hblock.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的人可以分享一些关于此的知识。

1 个答案:

答案 0 :(得分:6)

TL; DR版本:

如果您的好奇只是想知道struct dispatch_queue_s中的字段是什么,您可以在this file中自己阅读,但作为API的使用者/用户,您永远不需要知道这一点信息以便使用它。因为你永远不需要知道,并且因为该结构中的字段不是公共API的一部分,如果你使用这些知识(除了你自己的启发和娱乐),你就是在为自己设置麻烦。

长版:

让我们看看我是否可以在这里逐一进行:

  

来自用户的帖子想知道这意味着什么:

     

@property(非原子,强)属性((NSObject))   dispatch_queue_t captureQueue;据说他得到了一些错误   我以为我会谷歌,因为我也感兴趣。

     

有一件事导致了另一件事,这引出了我的问题:

ARC Documentation说:

  

__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。你可以使用你的声明可见的东西,但是它的定义并不是所有的时间(任何时候你调用库函数,如printfNSLog或其他什么。)通过类比,如果我给你邮寄信件的街道地址(指针),你会认为在那个地址有一座建筑物(指向的东西),但你不需要知道建筑物是房子,还是办公楼或其他什么,如果您与它的唯一互动是通过其地址发送和接收邮件。

_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);

...虽然表现不佳。希望这很有用。