---
name: "dispatch_queue_create"
section: "3"
platform: "linux"
package: "libdispatch"
version: "6.2.2-1"
release: "Arch Linux 2026-11-01"
platforms: ["linux", "macos"]
url: "https://new.carta.tech/dispatch_queue_create"
---

# dispatch\_queue\_create(3)

where blocks are scheduled for execution

## NAME

**dispatch\_queue\_create**, **dispatch\_queue\_get\_label**, **dispatch\_get\_current\_queue**, **dispatch\_get\_global\_queue**, **dispatch\_get\_main\_queue**, **dispatch\_main**, **dispatch\_set\_target\_queue** – where blocks are scheduled for execution

## SYNOPSIS

**#include \<dispatch/dispatch.h\>**

*dispatch\_queue\_t*\

**dispatch\_queue\_create**(*const char \*label*, *dispatch\_queue\_attr\_t attr*);

*const char \**\

**dispatch\_queue\_get\_label**(*dispatch\_queue\_t queue*);

*dispatch\_queue\_t*\

**dispatch\_get\_global\_queue**(*long priority*, *unsigned long flags*);

*dispatch\_queue\_t*\

**dispatch\_get\_main\_queue**(*void*);

*void*\

**dispatch\_main**(*void*);

*void*\

**dispatch\_set\_target\_queue**(*dispatch\_object\_t object*, *dispatch\_queue\_t target*);

## DESCRIPTION

Queues are the fundamental mechanism for scheduling blocks for execution within the [dispatch(3)](/dispatch/3.md) framework.

All blocks submitted to dispatch queues are dequeued in FIFO order. Queues created with the 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.

Queues created with the DISPATCH\_QUEUE\_CONCURRENT attribute may execute dequeued blocks concurrently and support barrier blocks submitted with the dispatch barrier API.

## CREATION

Queues are created with the **dispatch\_queue\_create**() function. Queues, like all dispatch objects, are reference counted and newly created queues have a reference count of one.

The optional *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:

```
my_queue = dispatch_queue_create("com.example.subsystem.taskXYZ",
				 DISPATCH_QUEUE_SERIAL);
```

The *attr* argument specifies the type of queue to create and must be either DISPATCH\_QUEUE\_SERIAL or DISPATCH\_QUEUE\_CONCURRENT.

The **dispatch\_queue\_get\_label**() function returns the label provided when the given *queue* was created (or an empty C string if no label was provided at creation). Passing the constant DISPATCH\_CURRENT\_QUEUE\_LABEL to **dispatch\_queue\_get\_label**() returns the label of the current queue.

## SUSPENSION

Queues may be temporarily suspended and resumed with the functions **dispatch\_suspend**() and **dispatch\_resume**() respectively. Suspension is checked prior to block execution and is *not* preemptive.

## MAIN QUEUE

The dispatch framework provides a default serial queue for the application to use. This queue is accessed via the **dispatch\_get\_main\_queue**() function.

Programs must call **dispatch\_main**() at the end of **main**() in order to process blocks submitted to the main queue. (See the COMPATIBILITY section for exceptions.) The **dispatch\_main**() function never returns.

## GLOBAL CONCURRENT QUEUES

Unlike the main queue or queues allocated with **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:

- DISPATCH\_QUEUE\_PRIORITY\_HIGH

- DISPATCH\_QUEUE\_PRIORITY\_DEFAULT

- DISPATCH\_QUEUE\_PRIORITY\_LOW

- DISPATCH\_QUEUE\_PRIORITY\_BACKGROUND

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 [setpriority(2)](/setpriority/2.md) (i.e. disk I/O is throttled and the thread's scheduling priority is set to lowest value).

Use the **dispatch\_get\_global\_queue**() function to obtain the global queue of given priority. The *flags* argument is reserved for future use and must be zero. Passing any value other than zero may result in a NULL return value.

## TARGET QUEUE

The **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.

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).

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 DISPATCH\_TARGET\_QUEUE\_DEFAULT constant to **dispatch\_set\_target\_queue**().

The priority of a dispatch queue is inherited from its target queue. In order to change the priority of a queue created with **dispatch\_queue\_create**(), use the **dispatch\_get\_global\_queue**() function to obtain a target queue of the desired priority.

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.

The target queue of a dispatch source specifies where its event handler and cancellation handler blocks will be submitted. See [dispatch\_source\_create(3)](/dispatch_source_create/3.md) for more information about dispatch sources.

The target queue of a dispatch I/O channel specifies the priority of the global queue where its I/O operations are executed. See [dispatch\_io\_create(3)](/dispatch_io_create/3.md) for more information about dispatch I/O channels.

For all other dispatch object types, the only function of the target queue is to determine where an object's finalizer function is invoked.

The result of passing the main queue or a global concurrent queue as the first argument of **dispatch\_set\_target\_queue**() is undefined.

Directly or indirectly setting the target queue of a dispatch queue to itself is undefined.

## DEPRECATED FUNCTIONS

The following functions are deprecated and will be removed in a future release:

-

  *dispatch\_queue\_t* **dispatch\_get\_current\_queue**(*void*);

**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 **dispatch\_main**() is called, then the result of **dispatch\_get\_main\_queue**() is returned. In all other cases, the default target queue will be returned.

The use of **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.

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 **dispatch\_get\_current\_queue**().

The result of **dispatch\_get\_main\_queue**() may or may not equal the result of **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 [pthread\_main\_np(3)](/pthread_main_np/3.md).

**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 **dispatch\_get\_current\_queue**() will cause retain calls to be automatically generated, so the use of **dispatch\_get\_current\_queue**() for any reason in code built with ARC is particularly strongly discouraged.

## COMPATIBILITY

Cocoa applications need not call **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 **dispatch\_main**() are not guaranteed to execute on the main thread.

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 *MUST* catch all exceptions before returning from a block submitted to a dispatch queue; otherwise the process will be terminated with an uncaught exception.

The dispatch framework manages the relationship between dispatch queues and threads of execution. As a result, applications *MUST* *NOT* delete or mutate objects that they did not create. The following interfaces *MUST* *NOT* be called by blocks submitted to a dispatch queue:

- **pthread\_cancel**()

- **pthread\_detach**()

- **pthread\_join**()

- **pthread\_kill**()

- **pthread\_exit**()

Applications *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:

- **pthread\_setcancelstate**()

- **pthread\_setcanceltype**()

- **pthread\_setschedparam**()

- **pthread\_sigmask**()

- **pthread\_setugid\_np**()

Applications *MUST* *NOT* rely on the following interfaces returning predictable results between invocations of blocks submitted to a dispatch queue:

- **pthread\_self**()

- **pthread\_getschedparam**()

- **pthread\_get\_stacksize\_np**()

- **pthread\_get\_stackaddr\_np**()

- **pthread\_mach\_thread\_np**()

- **pthread\_from\_mach\_thread\_np**()

While the result of **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 **pthread\_setspecific**() and **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 **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.

The following example code correctly handles per-thread return values:

```
__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 %d0, r, e);
```

Note that in the above example *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 **getpwnam**() instead of **getpwnam\_r**().

As an optimization, **dispatch\_sync**() invokes the block on the current thread when possible. In this case, the thread specific data such as *errno* may persist from the block until back to the caller. Great care should be taken not to accidentally rely on this side-effect.

## SEE ALSO

[dispatch(3)](/dispatch/3.md), [dispatch\_async(3)](/dispatch_async/3.md), [dispatch\_object(3)](/dispatch_object/3.md), [dispatch\_source\_create(3)](/dispatch_source_create/3.md)
