01. Dispatch

2018-10-30  本文已影响22人  ngugg

Execute code concurrently on multicore hardware by submitting work to dispatch queues managed by the system.

Overview

Dispatch comprises language features, runtime libraries, and system enhancements that provide systemic, comprehensive improvements to the support for concurrent code execution on multicore hardware in macOS, iOS, watchOS, and tvOS.

The BSD subsystem, Core Foundation, and Cocoa APIs have all been extended to use these enhancements to help both the system and your application to run faster, more efficiently, and with improved responsiveness. Consider how difficult it is for a single application to use multiple cores effectively, let alone doing it on different computers with different numbers of computing cores or in an environment with multiple applications competing for those cores. GCD, operating at the system level, can better accommodate the needs of all running applications, matching them to the available system resources in a balanced fashion.

Managing Dispatch Queues

GCD provides and manages FIFO queues to which your application can submit tasks in the form of block objects. Work submitted to dispatch queues are executed on a pool of threads fully managed by the system. No guarantee is made as to the thread on which a task executes.

Synchronous and Asynchronous Execution

Each work item can be executed either synchronously or asynchronously. When a work item is executed synchronously with the sync method, the program waits until execution finishes before the method call returns. When a work item is executed asynchronously with the async method, the method call returns immediately.

Serial and Concurrent Queues

A dispatch queue can be either serial, so that work items are executed one at a time, or it can be concurrent, so that work items are dequeued in order, but run all at once and can finish in any order. Both serial and concurrent queues process work items in first in, first-out (FIFO) order.

System-Provided Queues

When an app launches, the system automatically creates a special queue called the main queue. Work items enqueued to the main queue execute serially on your app’s main thread. You can access the main queue using the main type property.

Important
Attempting to synchronously execute a work item on the main queue results in dead-lock.

In addition to the serial main queue, the system also creates a number of global concurrent dispatch queues. You can access the global concurrent queue that best matches a specified quality of service (QoS) using the global(attributes:) type method.

class DispatchQueue

DispatchQueue manages the execution of work items. Each work item submitted to a queue is processed on a pool of threads managed by the system.

class DispatchSpecificKey

DispatchSpecificKey is a class that encapsulates keys that can be associated with a contextual value on a DispatchQueue using the setSpecific<T>(key:value:) method, and accessed using the getSpecific<T>(key:) method.

Managing Units of Work

Work items allow you to configure properties of individual units of work directly. They also allow you to address individual work units for the purposes of waiting for their completion, getting notified about their completion, and/or canceling them.

class DispatchWorkItem

DispatchWorkItem encapsulates work that can be performed. A work item can be dispatched onto a DispatchQueue and within a DispatchGroup. A DispatchWorkItem can also be set as a DispatchSource event, registration, or cancel handler.

struct DispatchWorkItemFlags

DispatchWorkItemFlags are an option set that configure the behavior of a DispatchWorkItem value, including its quality of service class and whether to create a barrier or spawn a new detached thread.

Prioritizing Work and Specifying Quality of Service

struct DispatchQoS

DispatchQoS encapsulates quality of service classes.

enum DispatchQoS.QoSClass

DispatchQoS.QoSClass encapsulates quality of service classes.

Dispatch Queue Priorities

Used to select the appropriate global concurrent queue.

Using Dispatch Groups

Grouping blocks allows for aggregate synchronization. Your application can submit multiple blocks and track when they all complete, even though they might run on different queues. This behavior can be helpful when progress can’t be made until all of the specified tasks are complete.

class DispatchGroup

DispatchGroup allows for aggregate synchronization of work. You can use them to submit multiple different work items and track when they all complete, even though they might run on different queues. This behavior can be helpful when progress can’t be made until all of the specified tasks are complete.

Using Dispatch Semaphores

A dispatch semaphore is an efficient implementation of a traditional counting semaphore. Dispatch semaphores call down to the kernel only when the calling thread needs to be blocked. If the calling semaphore does not need to block, no kernel call is made.

class DispatchSemaphore

DispatchSemaphore provides an efficient implementation of a traditional counting semaphore, which can be used to control access to a resource across multiple execution contexts.

Using Dispatch Data

struct DispatchData

DispatchData objects manage a memory-based data buffer. The data buffer is exposed as a contiguous block of memory, but internally, it may be comprised of multiple, discontiguous blocks of memory.

struct DispatchDataIterator

enum DispatchData.Deallocator

Using Dispatch Time

DispatchTime represents a point in time relative to the default clock with nanosecond precision. On Apple platforms, the default clock is based on the Mach absolute time unit.

Dispatch Time Constants

Base time constants. 基准时间常数。

struct DispatchWallTime

DispatchTime represents an absolute point in time according to the wall clock with microsecond precision. On Apple platforms, the default clock is based on the result of gettimeofday(2).

enum DispatchTimeInterval

DispatchTimeInterval represents a number of seconds, millisconds, microseconds, or nanoseconds. You use DispatchTimeInterval values to specify the interval at which a DispatchSourceTimer fires or I/O handlers are invoked for a DispatchIO channel, as well as to increment and decrement DispatchTime values.

enum DispatchTimeoutResult

DispatchTimeoutResult indicates whether a dispatch operation finised before a specified time.

Dispatch Time Operators

typealias dispatch_time_t

A somewhat abstract representation of time.

class DispatchSource

DispatchSource provides an interface for monitoring low-level system objects such as Mach ports, Unix descriptors, Unix signals, and VFS nodes for activity and submitting event handlers to dispatch queues for asynchronous processing when such activity occurs.

protocol DispatchSourceProtocol

Defines a common set of properties and methods that are shared with all dispatch source types.

protocol DispatchSourceFileSystemObject

A dispatch source that monitors a file descriptor for events defined by DispatchSource.FileSystemEvent. The handle is a file descriptor (Int32).

struct DispatchSource.FileSystemEvent

A file system event.

Managing Dispatch I/O

The dispatch I/O channel API lets you manage file descriptor–based operations. This API supports both stream-based and random-access semantics for accessing the contents of the file descriptor.

class DispatchIO

DispatchO provides a channel to perform operations on file descriptor using either stream-based and random-access semantics for accessing the contents of a file descriptor.

1. dispatch_barrier_async

Submits a barrier block for asynchronous execution and returns immediately.

Parameters
queue
The dispatch queue on which to execute the barrier block. The queue is retained by the system until the block has run to completion. This parameter cannot be NULL.

block
The barrier block to submit to the target dispatch queue. This block is copied and retained until it finishes executing, at which point it is released. This parameter cannot be NULL.

Discussion

Calls to this function always return immediately after the block has been submitted and never wait for the block to be invoked. When the barrier block reaches the front of a private concurrent queue, it is not executed immediately. Instead, the queue waits until its currently executing blocks finish executing. At that point, the barrier block executes by itself. Any blocks submitted after the barrier block are not executed until the barrier block completes.

The queue you specify should be a concurrent queue that you create yourself using the dispatch_queue_create function. If the queue you pass to this function is a serial queue or one of the global concurrent queues, this function behaves like the dispatch_async function.

2. dispatch_barrier_sync

Submits a barrier block object for execution and waits until that block completes.

Parameters
queue
The dispatch queue on which to execute the barrier block. This parameter cannot be NULL.

block
The barrier block to be executed. This parameter cannot be NULL.

Discussion

Submits a barrier block to a dispatch queue for synchronous execution. Unlike dispatch_barrier_async, this function does not return until the barrier block has finished. Calling this function and targeting the current queue results in deadlock.

When the barrier block reaches the front of a private concurrent queue, it is not executed immediately. Instead, the queue waits until its currently executing blocks finish executing. At that point, the queue executes the barrier block by itself. Any blocks submitted after the barrier block are not executed until the barrier block completes.

The queue you specify should be a concurrent queue that you create yourself using the dispatch_queue_create function. If the queue you pass to this function is a serial queue or one of the global concurrent queues, this function behaves like the dispatch_sync function.

Unlike with dispatch_barrier_async, no retain is performed on the target queue. Because calls to this function are synchronous, it "borrows" the reference of the caller. Moreover, no Block_copy is performed on the block.

As an optimization, this function invokes the barrier block on the current thread when possible.

dispatch_semaphore_wait

Waits for (decrements) a semaphore.

Parameters

dsema
The semaphore. This parameter cannot be NULL.

timeout
When to timeout (see dispatch_time). The constants DISPATCH_TIME_NOW and DISPATCH_TIME_FOREVER are available as a convenience.

Return Value
Returns zero on success, or non-zero if the timeout occurred.

Discussion
Decrement the counting semaphore. If the resulting value is less than zero, this function waits for a signal to occur before returning.

dispatch_semaphore_signal

Signals, or increments, a semaphore.

Return Value

If the previous value was less than zero, this function wakes a process currently waiting.

Discussion

Increment the counting semaphore. If the previous value was less than zero, this function wakes a thread currently waiting in dispatch_semaphore_wait.

dispatch_semaphore_create

Creates new counting semaphore with an initial value.

Parameters
value
The starting value for the semaphore. Do not pass a value less than zero.

Return Value
The newly created semaphore.

Discussion

Passing zero for the value is useful for when two threads need to reconcile the completion of a particular event. Passing a value greater than zero is useful for managing a finite pool of resources, where the pool size is equal to the value.

When your application no longer needs the semaphore, it should call dispatch_release to release its reference to the semaphore object and ultimately free its memory.

Important

Calls to dispatch_semaphore_signal must be balanced with calls to wait(). Attempting to dispose of a semaphore with a count lower than value causes an EXC_BAD_INSTRUCTION exception.

dispatch_sync

Submits a block object for execution on a dispatch queue and waits until that block completes.

Parameters
queue
The queue on which to submit the block. This parameter cannot be NULL.

block
The block to be invoked on the target dispatch queue. This parameter cannot be NULL.

Discussion

Submits a block to a dispatch queue for synchronous execution. Unlike dispatch_async, this function does not return until the block has finished. Calling this function and targeting the current queue results in deadlock.

Unlike with dispatch_async, no retain is performed on the target queue. Because calls to this function are synchronous, it "borrows" the reference of the caller. Moreover, no Block_copy is performed on the block.

As an optimization, this function invokes the block on the current thread when possible.

dispatch_async

Submits a block for asynchronous execution on a dispatch queue and returns immediately.

Parameters
queue
The queue on which to submit the block. The queue is retained by the system until the block has run to completion. This parameter cannot be NULL.

block
The block to submit to the target dispatch queue. This function performs Block_copy and Block_release on behalf of callers. This parameter cannot be NULL.

Discussion

This function is the fundamental mechanism for submitting blocks to a dispatch queue. Calls to this function always return immediately after the block has been submitted and never wait for the block to be invoked. The target queue determines whether the block is invoked serially or concurrently with respect to other blocks submitted to that same queue. Independent serial queues are processed concurrently with respect to each other.

上一篇下一篇

猜你喜欢

热点阅读