blob: cbdcb5eff848b766f82875522894cfa2f2b180be [file] [log] [blame]
/*
* Copyright (c) 2014 Apple Inc. All rights reserved.
*
* @APPLE_APACHE_LICENSE_HEADER_START@
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @APPLE_APACHE_LICENSE_HEADER_END@
*/
#ifndef __DISPATCH_BLOCK__
#define __DISPATCH_BLOCK__
#ifndef __DISPATCH_INDIRECT__
#error "Please #include <dispatch/dispatch.h> instead of this file directly."
#include <dispatch/base.h> // for HeaderDoc
#endif
#ifdef __BLOCKS__
/*!
* @group Dispatch block objects
*/
DISPATCH_ASSUME_NONNULL_BEGIN
__BEGIN_DECLS
/*!
* @typedef dispatch_block_flags_t
* Flags to pass to the dispatch_block_create* functions.
*
* @const DISPATCH_BLOCK_BARRIER
* Flag indicating that a dispatch block object should act as a barrier block
* when submitted to a DISPATCH_QUEUE_CONCURRENT queue.
* See dispatch_barrier_async() for details.
* This flag has no effect when the dispatch block object is invoked directly.
*
* @const DISPATCH_BLOCK_DETACHED
* Flag indicating that a dispatch block object should execute disassociated
* from current execution context attributes such as QOS class, os_activity_t
* and properties of the current IPC request (if any). If invoked directly, the
* block object will remove these attributes from the calling thread for the
* duration of the block body (before applying attributes assigned to the block
* object, if any). If submitted to a queue, the block object will be executed
* with the attributes of the queue (or any attributes specifically assigned to
* the block object).
*
* @const DISPATCH_BLOCK_ASSIGN_CURRENT
* Flag indicating that a dispatch block object should be assigned the execution
* context attributes that are current at the time the block object is created.
* This applies to attributes such as QOS class, os_activity_t and properties of
* the current IPC request (if any). If invoked directly, the block object will
* apply these attributes to the calling thread for the duration of the block
* body. If the block object is submitted to a queue, this flag replaces the
* default behavior of associating the submitted block instance with the
* execution context attributes that are current at the time of submission.
* If a specific QOS class is assigned with DISPATCH_BLOCK_NO_QOS_CLASS or
* dispatch_block_create_with_qos_class(), that QOS class takes precedence over
* the QOS class assignment indicated by this flag.
*
* @const DISPATCH_BLOCK_NO_QOS_CLASS
* Flag indicating that a dispatch block object should be not be assigned a QOS
* class. If invoked directly, the block object will be executed with the QOS
* class of the calling thread. If the block object is submitted to a queue,
* this replaces the default behavior of associating the submitted block
* instance with the QOS class current at the time of submission.
* This flag is ignored if a specific QOS class is assigned with
* dispatch_block_create_with_qos_class().
*
* @const DISPATCH_BLOCK_INHERIT_QOS_CLASS
* Flag indicating that execution of a dispatch block object submitted to a
* queue should prefer the QOS class assigned to the queue over the QOS class
* assigned to the block (resp. associated with the block at the time of
* submission). The latter will only be used if the queue in question does not
* have an assigned QOS class, as long as doing so does not result in a QOS
* class lower than the QOS class inherited from the queue's target queue.
* This flag is the default when a dispatch block object is submitted to a queue
* for asynchronous execution and has no effect when the dispatch block object
* is invoked directly. It is ignored if DISPATCH_BLOCK_ENFORCE_QOS_CLASS is
* also passed.
*
* @const DISPATCH_BLOCK_ENFORCE_QOS_CLASS
* Flag indicating that execution of a dispatch block object submitted to a
* queue should prefer the QOS class assigned to the block (resp. associated
* with the block at the time of submission) over the QOS class assigned to the
* queue, as long as doing so will not result in a lower QOS class.
* This flag is the default when a dispatch block object is submitted to a queue
* for synchronous execution or when the dispatch block object is invoked
* directly.
*/
DISPATCH_ENUM(dispatch_block_flags, unsigned long,
DISPATCH_BLOCK_BARRIER
DISPATCH_ENUM_API_AVAILABLE(macos(10.10), ios(8.0)) = 0x1,
DISPATCH_BLOCK_DETACHED
DISPATCH_ENUM_API_AVAILABLE(macos(10.10), ios(8.0)) = 0x2,
DISPATCH_BLOCK_ASSIGN_CURRENT
DISPATCH_ENUM_API_AVAILABLE(macos(10.10), ios(8.0)) = 0x4,
DISPATCH_BLOCK_NO_QOS_CLASS
DISPATCH_ENUM_API_AVAILABLE(macos(10.10), ios(8.0)) = 0x8,
DISPATCH_BLOCK_INHERIT_QOS_CLASS
DISPATCH_ENUM_API_AVAILABLE(macos(10.10), ios(8.0)) = 0x10,
DISPATCH_BLOCK_ENFORCE_QOS_CLASS
DISPATCH_ENUM_API_AVAILABLE(macos(10.10), ios(8.0)) = 0x20,
);
/*!
* @function dispatch_block_create
*
* @abstract
* Create a new dispatch block object on the heap from an existing block and
* the given flags.
*
* @discussion
* The provided block is Block_copy'ed to the heap and retained by the newly
* created dispatch block object.
*
* The returned dispatch block object is intended to be submitted to a dispatch
* queue with dispatch_async() and related functions, but may also be invoked
* directly. Both operations can be performed an arbitrary number of times but
* only the first completed execution of a dispatch block object can be waited
* on with dispatch_block_wait() or observed with dispatch_block_notify().
*
* If the returned dispatch block object is submitted to a dispatch queue, the
* submitted block instance will be associated with the QOS class current at the
* time of submission, unless one of the following flags assigned a specific QOS
* class (or no QOS class) at the time of block creation:
* - DISPATCH_BLOCK_ASSIGN_CURRENT
* - DISPATCH_BLOCK_NO_QOS_CLASS
* - DISPATCH_BLOCK_DETACHED
* The QOS class the block object will be executed with also depends on the QOS
* class assigned to the queue and which of the following flags was specified or
* defaulted to:
* - DISPATCH_BLOCK_INHERIT_QOS_CLASS (default for asynchronous execution)
* - DISPATCH_BLOCK_ENFORCE_QOS_CLASS (default for synchronous execution)
* See description of dispatch_block_flags_t for details.
*
* If the returned dispatch block object is submitted directly to a serial queue
* and is configured to execute with a specific QOS class, the system will make
* a best effort to apply the necessary QOS overrides to ensure that blocks
* submitted earlier to the serial queue are executed at that same QOS class or
* higher.
*
* @param flags
* Configuration flags for the block object.
* Passing a value that is not a bitwise OR of flags from dispatch_block_flags_t
* results in NULL being returned.
*
* @param block
* The block to create the dispatch block object from.
*
* @result
* The newly created dispatch block object, or NULL.
* When not building with Objective-C ARC, must be released with a -[release]
* message or the Block_release() function.
*/
API_AVAILABLE(macos(10.10), ios(8.0))
DISPATCH_EXPORT DISPATCH_NONNULL2 DISPATCH_RETURNS_RETAINED_BLOCK
DISPATCH_WARN_RESULT DISPATCH_NOTHROW
dispatch_block_t
dispatch_block_create(dispatch_block_flags_t flags, dispatch_block_t block);
/*!
* @function dispatch_block_create_with_qos_class
*
* @abstract
* Create a new dispatch block object on the heap from an existing block and
* the given flags, and assign it the specified QOS class and relative priority.
*
* @discussion
* The provided block is Block_copy'ed to the heap and retained by the newly
* created dispatch block object.
*
* The returned dispatch block object is intended to be submitted to a dispatch
* queue with dispatch_async() and related functions, but may also be invoked
* directly. Both operations can be performed an arbitrary number of times but
* only the first completed execution of a dispatch block object can be waited
* on with dispatch_block_wait() or observed with dispatch_block_notify().
*
* If invoked directly, the returned dispatch block object will be executed with
* the assigned QOS class as long as that does not result in a lower QOS class
* than what is current on the calling thread.
*
* If the returned dispatch block object is submitted to a dispatch queue, the
* QOS class it will be executed with depends on the QOS class assigned to the
* block, the QOS class assigned to the queue and which of the following flags
* was specified or defaulted to:
* - DISPATCH_BLOCK_INHERIT_QOS_CLASS: default for asynchronous execution
* - DISPATCH_BLOCK_ENFORCE_QOS_CLASS: default for synchronous execution
* See description of dispatch_block_flags_t for details.
*
* If the returned dispatch block object is submitted directly to a serial queue
* and is configured to execute with a specific QOS class, the system will make
* a best effort to apply the necessary QOS overrides to ensure that blocks
* submitted earlier to the serial queue are executed at that same QOS class or
* higher.
*
* @param flags
* Configuration flags for the new block object.
* Passing a value that is not a bitwise OR of flags from dispatch_block_flags_t
* results in NULL being returned.
*
* @param qos_class
* A QOS class value:
* - QOS_CLASS_USER_INTERACTIVE
* - QOS_CLASS_USER_INITIATED
* - QOS_CLASS_DEFAULT
* - QOS_CLASS_UTILITY
* - QOS_CLASS_BACKGROUND
* - QOS_CLASS_UNSPECIFIED
* Passing QOS_CLASS_UNSPECIFIED is equivalent to specifying the
* DISPATCH_BLOCK_NO_QOS_CLASS flag. Passing any other value results in NULL
* being returned.
*
* @param relative_priority
* A relative priority within the QOS class. This value is a negative
* offset from the maximum supported scheduler priority for the given class.
* Passing a value greater than zero or less than QOS_MIN_RELATIVE_PRIORITY
* results in NULL being returned.
*
* @param block
* The block to create the dispatch block object from.
*
* @result
* The newly created dispatch block object, or NULL.
* When not building with Objective-C ARC, must be released with a -[release]
* message or the Block_release() function.
*/
API_AVAILABLE(macos(10.10), ios(8.0))
DISPATCH_EXPORT DISPATCH_NONNULL4 DISPATCH_RETURNS_RETAINED_BLOCK
DISPATCH_WARN_RESULT DISPATCH_NOTHROW
dispatch_block_t
dispatch_block_create_with_qos_class(dispatch_block_flags_t flags,
dispatch_qos_class_t qos_class, int relative_priority,
dispatch_block_t block);
/*!
* @function dispatch_block_perform
*
* @abstract
* Create, synchronously execute and release a dispatch block object from the
* specified block and flags.
*
* @discussion
* Behaves identically to the sequence
* <code>
* dispatch_block_t b = dispatch_block_create(flags, block);
* b();
* Block_release(b);
* </code>
* but may be implemented more efficiently internally by not requiring a copy
* to the heap of the specified block or the allocation of a new block object.
*
* @param flags
* Configuration flags for the temporary block object.
* The result of passing a value that is not a bitwise OR of flags from
* dispatch_block_flags_t is undefined.
*
* @param block
* The block to create the temporary block object from.
*/
API_AVAILABLE(macos(10.10), ios(8.0))
DISPATCH_EXPORT DISPATCH_NONNULL2 DISPATCH_NOTHROW
void
dispatch_block_perform(dispatch_block_flags_t flags,
DISPATCH_NOESCAPE dispatch_block_t block);
/*!
* @function dispatch_block_wait
*
* @abstract
* Wait synchronously until execution of the specified dispatch block object has
* completed or until the specified timeout has elapsed.
*
* @discussion
* This function will return immediately if execution of the block object has
* already completed.
*
* It is not possible to wait for multiple executions of the same block object
* with this interface; use dispatch_group_wait() for that purpose. A single
* dispatch block object may either be waited on once and executed once,
* or it may be executed any number of times. The behavior of any other
* combination is undefined. Submission to a dispatch queue counts as an
* execution, even if cancellation (dispatch_block_cancel) means the block's
* code never runs.
*
* The result of calling this function from multiple threads simultaneously
* with the same dispatch block object is undefined, but note that doing so
* would violate the rules described in the previous paragraph.
*
* If this function returns indicating that the specified timeout has elapsed,
* then that invocation does not count as the one allowed wait.
*
* If at the time this function is called, the specified dispatch block object
* has been submitted directly to a serial queue, the system will make a best
* effort to apply the necessary QOS overrides to ensure that the block and any
* blocks submitted earlier to that serial queue are executed at the QOS class
* (or higher) of the thread calling dispatch_block_wait().
*
* @param block
* The dispatch block object to wait on.
* The result of passing NULL or a block object not returned by one of the
* dispatch_block_create* functions is undefined.
*
* @param timeout
* When to timeout (see dispatch_time). As a convenience, there are the
* DISPATCH_TIME_NOW and DISPATCH_TIME_FOREVER constants.
*
* @result
* Returns zero on success (the dispatch block object completed within the
* specified timeout) or non-zero on error (i.e. timed out).
*/
API_AVAILABLE(macos(10.10), ios(8.0))
DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NOTHROW
long
dispatch_block_wait(dispatch_block_t block, dispatch_time_t timeout);
/*!
* @function dispatch_block_notify
*
* @abstract
* Schedule a notification block to be submitted to a queue when the execution
* of a specified dispatch block object has completed.
*
* @discussion
* This function will submit the notification block immediately if execution of
* the observed block object has already completed.
*
* It is not possible to be notified of multiple executions of the same block
* object with this interface, use dispatch_group_notify() for that purpose.
*
* A single dispatch block object may either be observed one or more times
* and executed once, or it may be executed any number of times. The behavior
* of any other combination is undefined. Submission to a dispatch queue
* counts as an execution, even if cancellation (dispatch_block_cancel) means
* the block's code never runs.
*
* If multiple notification blocks are scheduled for a single block object,
* there is no defined order in which the notification blocks will be submitted
* to their associated queues.
*
* @param block
* The dispatch block object to observe.
* The result of passing NULL or a block object not returned by one of the
* dispatch_block_create* functions is undefined.
*
* @param queue
* The queue to which the supplied notification block will be submitted when
* the observed block completes.
*
* @param notification_block
* The notification block to submit when the observed block object completes.
*/
API_AVAILABLE(macos(10.10), ios(8.0))
DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
void
dispatch_block_notify(dispatch_block_t block, dispatch_queue_t queue,
dispatch_block_t notification_block);
/*!
* @function dispatch_block_cancel
*
* @abstract
* Asynchronously cancel the specified dispatch block object.
*
* @discussion
* Cancellation causes any future execution of the dispatch block object to
* return immediately, but does not affect any execution of the block object
* that is already in progress.
*
* Release of any resources associated with the block object will be delayed
* until execution of the block object is next attempted (or any execution
* already in progress completes).
*
* NOTE: care needs to be taken to ensure that a block object that may be
* canceled does not capture any resources that require execution of the
* block body in order to be released (e.g. memory allocated with
* malloc(3) that the block body calls free(3) on). Such resources will
* be leaked if the block body is never executed due to cancellation.
*
* @param block
* The dispatch block object to cancel.
* The result of passing NULL or a block object not returned by one of the
* dispatch_block_create* functions is undefined.
*/
API_AVAILABLE(macos(10.10), ios(8.0))
DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
void
dispatch_block_cancel(dispatch_block_t block);
/*!
* @function dispatch_block_testcancel
*
* @abstract
* Tests whether the given dispatch block object has been canceled.
*
* @param block
* The dispatch block object to test.
* The result of passing NULL or a block object not returned by one of the
* dispatch_block_create* functions is undefined.
*
* @result
* Non-zero if canceled and zero if not canceled.
*/
API_AVAILABLE(macos(10.10), ios(8.0))
DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_WARN_RESULT DISPATCH_PURE
DISPATCH_NOTHROW
long
dispatch_block_testcancel(dispatch_block_t block);
__END_DECLS
DISPATCH_ASSUME_NONNULL_END
#endif // __BLOCKS__
#endif // __DISPATCH_BLOCK__