| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371 |
- .\" Copyright (c) 2008-2012 Apple Inc. All rights reserved.
- .Dd May 1, 2008
- .Dt dispatch_queue_create 3
- .Os Darwin
- .Sh NAME
- .Nm dispatch_queue_create ,
- .Nm dispatch_queue_get_label ,
- .Nm dispatch_get_current_queue ,
- .Nm dispatch_get_global_queue ,
- .Nm dispatch_get_main_queue ,
- .Nm dispatch_main ,
- .Nm dispatch_set_target_queue
- .Nd where blocks are scheduled for execution
- .Sh SYNOPSIS
- .Fd #include <dispatch/dispatch.h>
- .Ft dispatch_queue_t
- .Fo dispatch_queue_create
- .Fa "const char *label" "dispatch_queue_attr_t attr"
- .Fc
- .Ft "const char *"
- .Fo dispatch_queue_get_label
- .Fa "dispatch_queue_t queue"
- .Fc
- .Ft dispatch_queue_t
- .Fo dispatch_get_global_queue
- .Fa "long priority"
- .Fa "unsigned long flags"
- .Fc
- .Ft dispatch_queue_t
- .Fo dispatch_get_main_queue
- .Fa void
- .Fc
- .Ft void
- .Fo dispatch_main
- .Fa void
- .Fc
- .Ft void
- .Fo dispatch_set_target_queue
- .Fa "dispatch_object_t object"
- .Fa "dispatch_queue_t target"
- .Fc
- .Sh DESCRIPTION
- Queues are the fundamental mechanism for scheduling blocks for execution within
- the
- .Xr dispatch 3
- framework.
- .Pp
- All blocks submitted to dispatch queues are dequeued in FIFO order.
- Queues created with the
- .Dv DISPATCH_QUEUE_SERIAL
- attribute wait for the previously dequeued block to complete before dequeuing
- the next block. A queue with this FIFO completion behavior is usually simply
- described as a "serial queue." All memory writes performed by a block dispatched
- to a serial queue are guaranteed to be visible to subsequent blocks dispatched
- to the same queue. Queues are not bound to any specific thread of execution and
- blocks submitted to independent queues may execute concurrently.
- .Pp
- Queues created with the
- .Dv DISPATCH_QUEUE_CONCURRENT
- attribute may execute dequeued blocks concurrently and support barrier blocks
- submitted with the dispatch barrier API.
- .Sh CREATION
- Queues are created with the
- .Fn dispatch_queue_create
- function. Queues, like all dispatch objects, are reference counted and newly
- created queues have a reference count of one.
- .Pp
- The optional
- .Fa label
- argument is used to describe the purpose of the queue and is useful during
- debugging and performance analysis. If a label is provided, it is copied.
- By convention, clients should pass a reverse DNS style label. For example:
- .Pp
- .Bd -literal -offset indent
- my_queue = dispatch_queue_create("com.example.subsystem.taskXYZ",
- DISPATCH_QUEUE_SERIAL);
- .Ed
- .Pp
- The
- .Fa attr
- argument specifies the type of queue to create and must be either
- .Dv DISPATCH_QUEUE_SERIAL
- or
- .Dv DISPATCH_QUEUE_CONCURRENT .
- .Pp
- The
- .Fn dispatch_queue_get_label
- function returns the label provided when the given
- .Fa queue
- was created (or an empty C string if no label was provided at creation).
- Passing the constant
- .Dv DISPATCH_CURRENT_QUEUE_LABEL
- to
- .Fn dispatch_queue_get_label
- returns the label of the current queue.
- .Sh SUSPENSION
- Queues may be temporarily suspended and resumed with the functions
- .Fn dispatch_suspend
- and
- .Fn dispatch_resume
- respectively. Suspension is checked prior to block execution and is
- .Em not
- preemptive.
- .Sh MAIN QUEUE
- The dispatch framework provides a default serial queue for the application to
- use. This queue is accessed via the
- .Fn dispatch_get_main_queue
- function.
- .Pp
- Programs must call
- .Fn dispatch_main
- at the end of
- .Fn main
- in order to process blocks submitted to the main queue. (See the
- .Sx COMPATIBILITY
- section for exceptions.) The
- .Fn dispatch_main
- function never returns.
- .Sh GLOBAL CONCURRENT QUEUES
- Unlike the main queue or queues allocated with
- .Fn dispatch_queue_create ,
- the global concurrent queues schedule blocks as soon as threads become
- available (non-FIFO completion order). Four global concurrent queues are
- provided, representing the following priority bands:
- .Bl -bullet -compact -offset indent
- .It
- DISPATCH_QUEUE_PRIORITY_HIGH
- .It
- DISPATCH_QUEUE_PRIORITY_DEFAULT
- .It
- DISPATCH_QUEUE_PRIORITY_LOW
- .It
- DISPATCH_QUEUE_PRIORITY_BACKGROUND
- .El
- .Pp
- The priority of a global concurrent queue controls the scheduling priority of
- the threads created by the system to invoke the blocks submitted to that queue.
- Global queues with lower priority will be scheduled for execution after all
- global queues with higher priority have been scheduled. Additionally, items on
- the background priority global queue will execute on threads with background
- state as described in
- .Xr setpriority 2
- (i.e.\& disk I/O is throttled and the thread's scheduling priority is set to
- lowest value).
- .Pp
- Use the
- .Fn dispatch_get_global_queue
- function to obtain the global queue of given priority. The
- .Fa flags
- argument is reserved for future use and must be zero. Passing any value other
- than zero may result in a NULL return value.
- .Sh TARGET QUEUE
- The
- .Fn dispatch_set_target_queue
- function updates the target queue of the given dispatch object. The target
- queue of an object is responsible for processing the object.
- .Pp
- The new target queue is retained by the given object before the previous target
- queue is released. The new target queue setting will take effect between block
- executions on the object, but not in the middle of any existing block executions
- (non-preemptive).
- .Pp
- The default target queue of all dispatch objects created by the application is
- the default priority global concurrent queue. To reset an object's target queue
- to the default, pass the
- .Dv DISPATCH_TARGET_QUEUE_DEFAULT
- constant to
- .Fn dispatch_set_target_queue .
- .Pp
- The priority of a dispatch queue is inherited from its target queue.
- In order to change the priority of a queue created with
- .Fn dispatch_queue_create ,
- use the
- .Fn dispatch_get_global_queue
- function to obtain a target queue of the desired priority.
- .Pp
- Blocks submitted to a serial queue whose target queue is another serial queue
- will not be invoked concurrently with blocks submitted to the target queue or
- to any other queue with that same target queue.
- .Pp
- The target queue of a dispatch source specifies where its event handler and
- cancellation handler blocks will be submitted. See
- .Xr dispatch_source_create 3
- for more information about dispatch sources.
- .Pp
- The target queue of a dispatch I/O channel specifies the priority of the global
- queue where its I/O operations are executed. See
- .Xr dispatch_io_create 3
- for more information about dispatch I/O channels.
- .Pp
- For all other dispatch object types, the only function of the target queue is
- to determine where an object's finalizer function is invoked.
- .Pp
- The result of passing the main queue or a global concurrent queue as the first
- argument of
- .Fn dispatch_set_target_queue
- is undefined.
- .Pp
- Directly or indirectly setting the target queue of a dispatch queue to itself is
- undefined.
- .Sh DEPRECATED FUNCTIONS
- The following functions are deprecated and will be removed in a future release:
- .Bl -item
- .It
- .Ft dispatch_queue_t
- .Fn dispatch_get_current_queue void ;
- .El
- .Pp
- .Fn dispatch_get_current_queue
- always returns a valid queue. When called from within a block
- submitted to a dispatch queue, that queue will be returned. If this function is
- called from the main thread before
- .Fn dispatch_main
- is called, then the result of
- .Fn dispatch_get_main_queue
- is returned. In all other cases, the default target queue will be returned.
- .Pp
- The use of
- .Fn dispatch_get_current_queue
- is strongly discouraged except for debugging and logging purposes. Code must not
- make any assumptions about the queue returned, unless it is one of the global
- queues or a queue the code has itself created. The returned queue may have
- arbitrary policies that may surprise code that tries to schedule work with the
- queue. The list of policies includes, but is not limited to, queue width (i.e.
- serial vs. concurrent), scheduling priority, security credential or filesystem
- configuration. This function is deprecated and will be removed in a future
- release.
- .Pp
- It is equally unsafe for code to assume that synchronous execution onto a queue
- is safe from deadlock if that queue is not the one returned by
- .Fn dispatch_get_current_queue .
- .Pp
- The result of
- .Fn dispatch_get_main_queue
- may or may not equal the result of
- .Fn dispatch_get_current_queue
- when called on the main thread. Comparing the two is not a valid way to test
- whether code is executing on the main thread. Foundation/AppKit programs should
- use [NSThread isMainThread]. POSIX programs may use
- .Xr pthread_main_np 3 .
- .Pp
- .Fn dispatch_get_current_queue
- may return a queue owned by a different subsystem which has already had all
- external references to it released. While such a queue will continue to exist
- until all blocks submitted to it have completed, attempting to retain it is
- forbidden and will trigger an assertion. If Objective-C Automatic Reference
- Counting is enabled, any use of the object returned by
- .Fn dispatch_get_current_queue
- will cause retain calls to be automatically generated, so the use of
- .Fn dispatch_get_current_queue
- for any reason in code built with ARC is particularly strongly discouraged.
- .Sh COMPATIBILITY
- Cocoa applications need not call
- .Fn dispatch_main .
- Blocks submitted to the main queue will be executed as part of the "common
- modes" of the application's main NSRunLoop or CFRunLoop.
- However, blocks submitted to the main queue in applications using
- .Fn dispatch_main
- are not guaranteed to execute on the main thread.
- .Pp
- The dispatch framework is a pure C level API. As a result, it does not catch
- exceptions generated by higher level languages such as Objective-C or C++.
- Applications
- .Em MUST
- catch all exceptions before returning from a block submitted to a dispatch
- queue; otherwise the process will be terminated with an uncaught exception.
- .Pp
- The dispatch framework manages the relationship between dispatch queues and
- threads of execution. As a result, applications
- .Em MUST NOT
- delete or mutate objects that they did not create. The following interfaces
- .Em MUST NOT
- be called by blocks submitted to a dispatch queue:
- .Bl -bullet -offset indent
- .It
- .Fn pthread_cancel
- .It
- .Fn pthread_detach
- .It
- .Fn pthread_join
- .It
- .Fn pthread_kill
- .It
- .Fn pthread_exit
- .El
- .Pp
- Applications
- .Em MAY
- call the following interfaces from a block submitted to a dispatch queue if
- and only if they restore the thread to its original state before returning:
- .Bl -bullet -offset indent
- .It
- .Fn pthread_setcancelstate
- .It
- .Fn pthread_setcanceltype
- .It
- .Fn pthread_setschedparam
- .It
- .Fn pthread_sigmask
- .It
- .Fn pthread_setugid_np
- .El
- .Pp
- Applications
- .Em MUST NOT
- rely on the following interfaces returning predictable results between
- invocations of blocks submitted to a dispatch queue:
- .Bl -bullet -offset indent
- .It
- .Fn pthread_self
- .It
- .Fn pthread_getschedparam
- .It
- .Fn pthread_get_stacksize_np
- .It
- .Fn pthread_get_stackaddr_np
- .It
- .Fn pthread_mach_thread_np
- .It
- .Fn pthread_from_mach_thread_np
- .El
- .Pp
- While the result of
- .Fn pthread_self
- may change between invocations of blocks, the value will not change during the
- execution of any single block. Because the underlying thread may change beteween
- block invocations on a single queue, using per-thread data as an out-of-band
- return value is error prone. In other words, the result of calling
- .Fn pthread_setspecific
- and
- .Fn pthread_getspecific
- is well defined within a signle block, but not across multiple blocks. Also,
- one cannot make any assumptions about when the destructor passed to
- .Fn pthread_key_create
- is called. The destructor may be called between the invocation of blocks on
- the same queue, or during the idle state of a process.
- .Pp
- The following example code correctly handles per-thread return values:
- .Bd -literal -offset indent
- __block int r;
- __block int e;
- dispatch_sync(queue, ^{
- r = kill(1, 0);
- // Copy the per-thread return value to the callee thread
- e = errno;
- });
- printf("kill(1,0) returned %d and errno %d\n", r, e);
- .Ed
- .Pp
- Note that in the above example
- .Va errno
- is a per-thread variable and must be copied out explicitly as the block may be
- invoked on different thread of execution than the caller. Another example of
- per-thread data that would need to be copied is the use of
- .Fn getpwnam
- instead of
- .Fn getpwnam_r .
- .Pp
- As an optimization,
- .Fn dispatch_sync
- invokes the block on the current thread when possible. In this case, the thread
- specific data such as
- .Va errno
- may persist from the block until back to the caller. Great care should be taken
- not to accidentally rely on this side-effect.
- .Pp
- .Sh SEE ALSO
- .Xr dispatch 3 ,
- .Xr dispatch_async 3 ,
- .Xr dispatch_object 3 ,
- .Xr dispatch_source_create 3
|