// This file has been automatically generated by `objc2`'s `header-translator`.
// DO NOT EDIT

#![allow(unused_imports)]
#![allow(deprecated)]
#![allow(non_snake_case)]
#![allow(non_camel_case_types)]
#![allow(non_upper_case_globals)]
#![allow(missing_docs)]
#![allow(clippy::too_many_arguments)]
#![allow(clippy::type_complexity)]
#![allow(clippy::upper_case_acronyms)]
#![allow(clippy::identity_op)]
#![allow(clippy::missing_safety_doc)]
#![allow(clippy::doc_lazy_continuation)]
#![allow(rustdoc::broken_intra_doc_links)]
#![allow(rustdoc::bare_urls)]
#![allow(rustdoc::unportable_markdown)]
#![allow(rustdoc::invalid_html_tags)]

use core::ffi::*;
use core::ptr::NonNull;
#[cfg(feature = "objc2")]
use objc2::__framework_prelude::*;

use crate::*;

/// [Apple's documentation](https://developer.apple.com/documentation/dispatch/dispatch_api_version?language=objc)
pub const DISPATCH_API_VERSION: c_uint = 20181008;
impl DispatchTime {
    /// Create a dispatch_time_t relative to the current value of the default or
    /// wall time clock, or modify an existing dispatch_time_t.
    ///
    ///
    /// On Apple platforms, the default clock is based on mach_absolute_time().
    ///
    ///
    /// Parameter `when`: An optional dispatch_time_t to add nanoseconds to. If DISPATCH_TIME_NOW is
    /// passed, then dispatch_time() will use the default clock (which is based on
    /// mach_absolute_time() on Apple platforms). If DISPATCH_WALLTIME_NOW is used,
    /// dispatch_time() will use the value returned by gettimeofday(3).
    /// dispatch_time(DISPATCH_WALLTIME_NOW, delta) is equivalent to
    /// dispatch_walltime(NULL, delta).
    ///
    ///
    /// Parameter `delta`: Nanoseconds to add.
    ///
    ///
    /// Returns: A new dispatch_time_t.
    #[doc(alias = "dispatch_time")]
    #[must_use]
    #[inline]
    pub fn time(self: DispatchTime, delta: i64) -> DispatchTime {
        extern "C" {
            fn dispatch_time(when: DispatchTime, delta: i64) -> DispatchTime;
        }
        unsafe { dispatch_time(self, delta) }
    }

    /// Create a dispatch_time_t using the wall clock.
    ///
    ///
    /// On Mac OS X the wall clock is based on gettimeofday(3).
    ///
    ///
    /// Parameter `when`: A struct timespec to add time to. If NULL is passed, then
    /// dispatch_walltime() will use the result of gettimeofday(3).
    /// dispatch_walltime(NULL, delta) returns the same value as
    /// dispatch_time(DISPATCH_WALLTIME_NOW, delta).
    ///
    ///
    /// Parameter `delta`: Nanoseconds to add.
    ///
    ///
    /// Returns: A new dispatch_time_t.
    #[doc(alias = "dispatch_walltime")]
    #[cfg(feature = "libc")]
    #[must_use]
    #[inline]
    pub unsafe fn walltime(when: *const libc::timespec, delta: i64) -> DispatchTime {
        extern "C" {
            fn dispatch_walltime(when: *const libc::timespec, delta: i64) -> DispatchTime;
        }
        unsafe { dispatch_walltime(when, delta) }
    }
}

/// The type of blocks submitted to dispatch queues, which take no arguments
/// and have no return value.
///
///
/// When not building with Objective-C ARC, a block object allocated on or
/// copied to the heap must be released with a -[release] message or the
/// Block_release() function.
///
/// The declaration of a block literal allocates storage on the stack.
/// Therefore, this is an invalid construct:
/// <code>
/// dispatch_block_t block;
/// if (x) {
/// block = ^{ printf("true\n"); };
/// } else {
/// block = ^{ printf("false\n"); };
/// }
/// block(); // unsafe!!!
/// </code>
///
/// What is happening behind the scenes:
/// <code>
/// if (x) {
/// struct Block __tmp_1 = ...; // setup details
/// block =
/// &
/// __tmp_1;
/// } else {
/// struct Block __tmp_2 = ...; // setup details
/// block =
/// &
/// __tmp_2;
/// }
/// </code>
///
/// As the example demonstrates, the address of a stack variable is escaping the
/// scope in which it is allocated. That is a classic C bug.
///
/// Instead, the block literal must be copied to the heap with the Block_copy()
/// function or by sending it a -[copy] message.
///
/// See also [Apple's documentation](https://developer.apple.com/documentation/dispatch/dispatch_block_t?language=objc)
#[cfg(feature = "block2")]
pub type dispatch_block_t = *mut block2::DynBlock<dyn Fn()>;

extern "C" {
    /// Increment the reference count of a dispatch object.
    ///
    ///
    /// Calls to dispatch_retain() must be balanced with calls to
    /// dispatch_release().
    ///
    ///
    /// Parameter `object`: The object to retain.
    /// The result of passing NULL in this parameter is undefined.
    pub fn dispatch_retain(object: NonNull<dispatch_object_s>);
}

extern "C" {
    /// Decrement the reference count of a dispatch object.
    ///
    ///
    /// A dispatch object is asynchronously deallocated once all references are
    /// released (i.e. the reference count becomes zero). The system does not
    /// guarantee that a given client is the last or only reference to a given
    /// object.
    ///
    ///
    /// Parameter `object`: The object to release.
    /// The result of passing NULL in this parameter is undefined.
    pub fn dispatch_release(object: NonNull<dispatch_object_s>);
}

/// Returns the application defined context of the object.
///
///
/// Parameter `object`: The result of passing NULL in this parameter is undefined.
///
///
/// Returns: The context of the object; may be NULL.
#[must_use]
#[inline]
pub extern "C" fn dispatch_get_context(object: NonNull<dispatch_object_s>) -> *mut c_void {
    extern "C" {
        fn dispatch_get_context(object: NonNull<dispatch_object_s>) -> *mut c_void;
    }
    unsafe { dispatch_get_context(object) }
}

extern "C" {
    /// Associates an application defined context with the object.
    ///
    ///
    /// Parameter `object`: The result of passing NULL in this parameter is undefined.
    ///
    ///
    /// Parameter `context`: The new client defined context for the object. This may be NULL.
    pub fn dispatch_set_context(object: NonNull<dispatch_object_s>, context: *mut c_void);
}

extern "C" {
    /// Set the finalizer function for a dispatch object.
    ///
    ///
    /// Parameter `object`: The dispatch object to modify.
    /// The result of passing NULL in this parameter is undefined.
    ///
    ///
    /// Parameter `finalizer`: The finalizer function pointer.
    ///
    ///
    /// A dispatch object's finalizer will be invoked on the object's target queue
    /// after all references to the object have been released. This finalizer may be
    /// used by the application to release any resources associated with the object,
    /// such as freeing the object's context.
    /// The context parameter passed to the finalizer function is the current
    /// context of the dispatch object at the time the finalizer call is made.
    pub fn dispatch_set_finalizer_f(
        object: NonNull<dispatch_object_s>,
        finalizer: dispatch_function_t,
    );
}

/// Activates the specified dispatch object.
///
///
/// Dispatch objects such as queues and sources may be created in an inactive
/// state. Objects in this state have to be activated before any blocks
/// associated with them will be invoked.
///
/// The target queue of inactive objects can be changed using
/// dispatch_set_target_queue(). Change of target queue is no longer permitted
/// once an initially inactive object has been activated.
///
/// Calling dispatch_activate() on an active object has no effect.
/// Releasing the last reference count on an inactive object is undefined.
///
///
/// Parameter `object`: The object to be activated.
/// The result of passing NULL in this parameter is undefined.
#[inline]
pub extern "C" fn dispatch_activate(object: NonNull<dispatch_object_s>) {
    extern "C" {
        fn dispatch_activate(object: NonNull<dispatch_object_s>);
    }
    unsafe { dispatch_activate(object) }
}

/// Suspends the invocation of blocks on a dispatch object.
///
///
/// A suspended object will not invoke any blocks associated with it. The
/// suspension of an object will occur after any running block associated with
/// the object completes.
///
/// Calls to dispatch_suspend() must be balanced with calls
/// to dispatch_resume().
///
///
/// Parameter `object`: The object to be suspended.
/// The result of passing NULL in this parameter is undefined.
#[inline]
pub extern "C" fn dispatch_suspend(object: NonNull<dispatch_object_s>) {
    extern "C" {
        fn dispatch_suspend(object: NonNull<dispatch_object_s>);
    }
    unsafe { dispatch_suspend(object) }
}

/// Resumes the invocation of blocks on a dispatch object.
///
///
/// Dispatch objects can be suspended with dispatch_suspend(), which increments
/// an internal suspension count. dispatch_resume() is the inverse operation,
/// and consumes suspension counts. When the last suspension count is consumed,
/// blocks associated with the object will be invoked again.
///
/// For backward compatibility reasons, dispatch_resume() on an inactive and not
/// otherwise suspended dispatch source object has the same effect as calling
/// dispatch_activate(). For new code, using dispatch_activate() is preferred.
///
/// If the specified object has zero suspension count and is not an inactive
/// source, this function will result in an assertion and the process being
/// terminated.
///
///
/// Parameter `object`: The object to be resumed.
/// The result of passing NULL in this parameter is undefined.
#[inline]
pub extern "C" fn dispatch_resume(object: NonNull<dispatch_object_s>) {
    extern "C" {
        fn dispatch_resume(object: NonNull<dispatch_object_s>);
    }
    unsafe { dispatch_resume(object) }
}

extern "C" {
    /// Sets the QOS class floor on a dispatch queue, source or workloop.
    ///
    ///
    /// The QOS class of workitems submitted to this object asynchronously will be
    /// elevated to at least the specified QOS class floor. The QOS of the workitem
    /// will be used if higher than the floor even when the workitem has been created
    /// without "ENFORCE" semantics.
    ///
    /// Setting the QOS class floor is equivalent to the QOS effects of configuring
    /// a queue whose target queue has a QoS class set to the same value.
    ///
    ///
    /// Parameter `object`: A dispatch queue, workloop, or source to configure.
    /// The object must be inactive.
    ///
    /// Passing another object type or an object that has been activated is undefined
    /// and will cause the process to be terminated.
    ///
    ///
    /// Parameter `qos_class`: A QOS class value:
    /// - QOS_CLASS_USER_INTERACTIVE
    /// - QOS_CLASS_USER_INITIATED
    /// - QOS_CLASS_DEFAULT
    /// - QOS_CLASS_UTILITY
    /// - QOS_CLASS_BACKGROUND
    /// Passing any other value is undefined.
    ///
    ///
    /// Parameter `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
    /// is undefined.
    pub fn dispatch_set_qos_class_floor(
        object: NonNull<dispatch_object_s>,
        qos_class: DispatchQoS,
        relative_priority: c_int,
    );
}

impl DispatchQueue {
    #[doc(alias = "dispatch_async")]
    #[cfg(feature = "block2")]
    #[inline]
    pub unsafe fn exec_async_with_block(self: &DispatchQueue, block: dispatch_block_t) {
        extern "C" {
            fn dispatch_async(queue: &DispatchQueue, block: dispatch_block_t);
        }
        unsafe { dispatch_async(self, block) }
    }

    /// Submits a function for asynchronous execution on a dispatch queue.
    ///
    ///
    /// See dispatch_async() for details.
    ///
    ///
    /// Parameter `queue`: The target dispatch queue to which the function is submitted.
    /// The system will hold a reference on the target queue until the function
    /// has returned.
    /// The result of passing NULL in this parameter is undefined.
    ///
    ///
    /// Parameter `context`: The application-defined context parameter to pass to the function.
    ///
    ///
    /// Parameter `work`: The application-defined function to invoke on the target queue. The first
    /// parameter passed to this function is the context provided to
    /// dispatch_async_f().
    /// The result of passing NULL in this parameter is undefined.
    #[doc(alias = "dispatch_async_f")]
    #[inline]
    pub unsafe fn exec_async_f(
        self: &DispatchQueue,
        context: *mut c_void,
        work: dispatch_function_t,
    ) {
        extern "C" {
            fn dispatch_async_f(
                queue: &DispatchQueue,
                context: *mut c_void,
                work: dispatch_function_t,
            );
        }
        unsafe { dispatch_async_f(self, context, work) }
    }

    #[doc(alias = "dispatch_sync")]
    #[cfg(feature = "block2")]
    #[inline]
    pub unsafe fn exec_sync_with_block(self: &DispatchQueue, block: dispatch_block_t) {
        extern "C" {
            fn dispatch_sync(queue: &DispatchQueue, block: dispatch_block_t);
        }
        unsafe { dispatch_sync(self, block) }
    }

    /// Submits a function for synchronous execution on a dispatch queue.
    ///
    ///
    /// See dispatch_sync() for details.
    ///
    ///
    /// Parameter `queue`: The target dispatch queue to which the function is submitted.
    /// The result of passing NULL in this parameter is undefined.
    ///
    ///
    /// Parameter `context`: The application-defined context parameter to pass to the function.
    ///
    ///
    /// Parameter `work`: The application-defined function to invoke on the target queue. The first
    /// parameter passed to this function is the context provided to
    /// dispatch_sync_f().
    /// The result of passing NULL in this parameter is undefined.
    #[doc(alias = "dispatch_sync_f")]
    #[inline]
    pub unsafe fn exec_sync_f(
        self: &DispatchQueue,
        context: *mut c_void,
        work: dispatch_function_t,
    ) {
        extern "C" {
            fn dispatch_sync_f(
                queue: &DispatchQueue,
                context: *mut c_void,
                work: dispatch_function_t,
            );
        }
        unsafe { dispatch_sync_f(self, context, work) }
    }

    #[doc(alias = "dispatch_async_and_wait")]
    #[cfg(feature = "block2")]
    #[inline]
    pub unsafe fn exec_sync_and_wait_with_block(self: &DispatchQueue, block: dispatch_block_t) {
        extern "C" {
            fn dispatch_async_and_wait(queue: &DispatchQueue, block: dispatch_block_t);
        }
        unsafe { dispatch_async_and_wait(self, block) }
    }

    /// Submits a function for synchronous execution on a dispatch queue.
    ///
    ///
    /// See dispatch_async_and_wait() for details.
    ///
    ///
    /// Parameter `queue`: The target dispatch queue to which the function is submitted.
    /// The result of passing NULL in this parameter is undefined.
    ///
    ///
    /// Parameter `context`: The application-defined context parameter to pass to the function.
    ///
    ///
    /// Parameter `work`: The application-defined function to invoke on the target queue. The first
    /// parameter passed to this function is the context provided to
    /// dispatch_async_and_wait_f().
    /// The result of passing NULL in this parameter is undefined.
    #[doc(alias = "dispatch_async_and_wait_f")]
    #[inline]
    pub unsafe fn exec_sync_and_wait_f(
        self: &DispatchQueue,
        context: *mut c_void,
        work: dispatch_function_t,
    ) {
        extern "C" {
            fn dispatch_async_and_wait_f(
                queue: &DispatchQueue,
                context: *mut c_void,
                work: dispatch_function_t,
            );
        }
        unsafe { dispatch_async_and_wait_f(self, context, work) }
    }

    #[doc(alias = "dispatch_apply")]
    #[cfg(feature = "block2")]
    #[inline]
    pub fn apply_with_block(
        iterations: usize,
        queue: Option<&DispatchQueue>,
        block: &block2::DynBlock<dyn Fn(usize)>,
    ) {
        extern "C" {
            fn dispatch_apply(
                iterations: usize,
                queue: Option<&DispatchQueue>,
                block: &block2::DynBlock<dyn Fn(usize)>,
            );
        }
        unsafe { dispatch_apply(iterations, queue, block) }
    }

    /// Submits a function to a dispatch queue for parallel invocation.
    ///
    ///
    /// See dispatch_apply() for details.
    ///
    ///
    /// Parameter `iterations`: The number of iterations to perform.
    ///
    ///
    /// Parameter `queue`: The dispatch queue to which the function is submitted.
    /// The preferred value to pass is DISPATCH_APPLY_AUTO to automatically use
    /// a queue appropriate for the calling thread.
    ///
    ///
    /// Parameter `context`: The application-defined context parameter to pass to the function.
    ///
    ///
    /// Parameter `work`: The application-defined function to invoke on the specified queue. The first
    /// parameter passed to this function is the context provided to
    /// dispatch_apply_f(). The second parameter passed to this function is the
    /// current index of iteration.
    /// The result of passing NULL in this parameter is undefined.
    #[doc(alias = "dispatch_apply_f")]
    #[inline]
    pub unsafe fn apply_f(
        iterations: usize,
        queue: Option<&DispatchQueue>,
        context: *mut c_void,
        work: unsafe extern "C-unwind" fn(*mut c_void, usize),
    ) {
        extern "C" {
            fn dispatch_apply_f(
                iterations: usize,
                queue: Option<&DispatchQueue>,
                context: *mut c_void,
                work: unsafe extern "C-unwind" fn(*mut c_void, usize),
            );
        }
        unsafe { dispatch_apply_f(iterations, queue, context, work) }
    }

    /// Returns the queue on which the currently executing block is running.
    ///
    ///
    /// Returns the queue on which the currently executing block is running.
    ///
    /// When dispatch_get_current_queue() is called outside of the context of a
    /// submitted block, it will return the default concurrent queue.
    ///
    /// Recommended for debugging and logging purposes only:
    /// The 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 code must not assume that synchronous execution onto a queue is safe
    /// from deadlock if that queue is not the one returned by
    /// dispatch_get_current_queue().
    ///
    /// When dispatch_get_current_queue() is called on the main thread, it may
    /// or may not return the same value as dispatch_get_main_queue(). Comparing
    /// the two is not a valid way to test whether code is executing on the
    /// main thread (see dispatch_assert_queue() and dispatch_assert_queue_not()).
    ///
    /// This function is deprecated and will be removed in a future release.
    ///
    ///
    /// Returns: Returns the current queue.
    #[doc(alias = "dispatch_get_current_queue")]
    #[deprecated = "unsupported interface"]
    #[must_use]
    #[inline]
    pub fn current() -> DispatchRetained<DispatchQueue> {
        extern "C" {
            fn dispatch_get_current_queue() -> Option<NonNull<DispatchQueue>>;
        }
        let ret = unsafe { dispatch_get_current_queue() };
        let ret =
            ret.expect("function was marked as returning non-null, but actually returned NULL");
        unsafe { DispatchRetained::retain(ret) }
    }
}

extern "C" {
    /// [Apple's documentation](https://developer.apple.com/documentation/dispatch/_dispatch_main_q?language=objc)
    pub static _dispatch_main_q: DispatchQueue;
}

/// Returns a well-known global concurrent queue of a given quality of service
/// class.
///
///
/// See dispatch_queue_global_t.
///
///
/// Parameter `identifier`: A quality of service class defined in qos_class_t or a priority defined in
/// dispatch_queue_priority_t.
///
/// It is recommended to use quality of service class values to identify the
/// well-known global concurrent queues:
/// - QOS_CLASS_USER_INTERACTIVE
/// - QOS_CLASS_USER_INITIATED
/// - QOS_CLASS_DEFAULT
/// - QOS_CLASS_UTILITY
/// - QOS_CLASS_BACKGROUND
///
/// The global concurrent queues may still be identified by their priority,
/// which map to the following QOS classes:
/// - DISPATCH_QUEUE_PRIORITY_HIGH:         QOS_CLASS_USER_INITIATED
/// - DISPATCH_QUEUE_PRIORITY_DEFAULT:      QOS_CLASS_DEFAULT
/// - DISPATCH_QUEUE_PRIORITY_LOW:          QOS_CLASS_UTILITY
/// - DISPATCH_QUEUE_PRIORITY_BACKGROUND:   QOS_CLASS_BACKGROUND
///
///
/// Parameter `flags`: Reserved for future use. Passing any value other than zero may result in
/// a NULL return value.
///
///
/// Returns: Returns the requested global queue or NULL if the requested global queue
/// does not exist.
#[must_use]
#[inline]
pub extern "C" fn dispatch_get_global_queue(
    identifier: isize,
    flags: usize,
) -> DispatchRetained<DispatchQueue> {
    extern "C" {
        fn dispatch_get_global_queue(
            identifier: isize,
            flags: usize,
        ) -> Option<NonNull<DispatchQueue>>;
    }
    let ret = unsafe { dispatch_get_global_queue(identifier, flags) };
    let ret = ret.expect("function was marked as returning non-null, but actually returned NULL");
    unsafe { DispatchRetained::retain(ret) }
}

extern "C" {
    /// [Apple's documentation](https://developer.apple.com/documentation/dispatch/_dispatch_queue_attr_concurrent?language=objc)
    pub static _dispatch_queue_attr_concurrent: DispatchQueueAttr;
}

impl DispatchQueueAttr {
    /// Returns an attribute value which may be provided to dispatch_queue_create()
    /// or dispatch_queue_create_with_target(), in order to make the created queue
    /// initially inactive.
    ///
    ///
    /// Dispatch queues may be created in an inactive state. Queues in this state
    /// have to be activated before any blocks associated with them will be invoked.
    ///
    /// A queue in inactive state cannot be deallocated, dispatch_activate() must be
    /// called before the last reference to a queue created with this attribute is
    /// released.
    ///
    /// The target queue of a queue in inactive state can be changed using
    /// dispatch_set_target_queue(). Change of target queue is no longer permitted
    /// once an initially inactive queue has been activated.
    ///
    ///
    /// Parameter `attr`: A queue attribute value to be combined with the initially inactive attribute.
    ///
    ///
    /// Returns: Returns an attribute value which may be provided to dispatch_queue_create()
    /// and dispatch_queue_create_with_target().
    /// The new value combines the attributes specified by the 'attr' parameter with
    /// the initially inactive attribute.
    #[doc(alias = "dispatch_queue_attr_make_initially_inactive")]
    #[must_use]
    #[inline]
    pub fn new_initially_inactive(
        attr: Option<&DispatchQueueAttr>,
    ) -> DispatchRetained<DispatchQueueAttr> {
        extern "C" {
            fn dispatch_queue_attr_make_initially_inactive(
                attr: Option<&DispatchQueueAttr>,
            ) -> Option<NonNull<DispatchQueueAttr>>;
        }
        let ret = unsafe { dispatch_queue_attr_make_initially_inactive(attr) };
        let ret =
            ret.expect("function was marked as returning non-null, but actually returned NULL");
        unsafe { DispatchRetained::retain(ret) }
    }
}

/// Values to pass to the dispatch_queue_attr_make_with_autorelease_frequency()
/// function.
///
///
/// Dispatch queues with this autorelease frequency inherit the behavior from
/// their target queue. This is the default behavior for manually created queues.
///
///
/// Dispatch queues with this autorelease frequency push and pop an autorelease
/// pool around the execution of every block that was submitted to it
/// asynchronously.
///
/// See: dispatch_queue_attr_make_with_autorelease_frequency().
///
///
/// Dispatch queues with this autorelease frequency never set up an individual
/// autorelease pool around the execution of a block that is submitted to it
/// asynchronously. This is the behavior of the global concurrent queues.
///
/// See also [Apple's documentation](https://developer.apple.com/documentation/dispatch/dispatchautoreleasefrequency?language=objc)
#[doc(alias = "dispatch_autorelease_frequency_t")] // NS_ENUM
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct DispatchAutoReleaseFrequency(pub c_ulong);
impl DispatchAutoReleaseFrequency {
    /// Values to pass to the dispatch_queue_attr_make_with_autorelease_frequency()
    /// function.
    ///
    ///
    /// Dispatch queues with this autorelease frequency inherit the behavior from
    /// their target queue. This is the default behavior for manually created queues.
    ///
    ///
    /// Dispatch queues with this autorelease frequency push and pop an autorelease
    /// pool around the execution of every block that was submitted to it
    /// asynchronously.
    ///
    /// See: dispatch_queue_attr_make_with_autorelease_frequency().
    ///
    ///
    /// Dispatch queues with this autorelease frequency never set up an individual
    /// autorelease pool around the execution of a block that is submitted to it
    /// asynchronously. This is the behavior of the global concurrent queues.
    #[doc(alias = "DISPATCH_AUTORELEASE_FREQUENCY_INHERIT")]
    pub const INHERIT: Self = Self(0);
    /// Values to pass to the dispatch_queue_attr_make_with_autorelease_frequency()
    /// function.
    ///
    ///
    /// Dispatch queues with this autorelease frequency inherit the behavior from
    /// their target queue. This is the default behavior for manually created queues.
    ///
    ///
    /// Dispatch queues with this autorelease frequency push and pop an autorelease
    /// pool around the execution of every block that was submitted to it
    /// asynchronously.
    ///
    /// See: dispatch_queue_attr_make_with_autorelease_frequency().
    ///
    ///
    /// Dispatch queues with this autorelease frequency never set up an individual
    /// autorelease pool around the execution of a block that is submitted to it
    /// asynchronously. This is the behavior of the global concurrent queues.
    #[doc(alias = "DISPATCH_AUTORELEASE_FREQUENCY_WORK_ITEM")]
    pub const WORK_ITEM: Self = Self(1);
    /// Values to pass to the dispatch_queue_attr_make_with_autorelease_frequency()
    /// function.
    ///
    ///
    /// Dispatch queues with this autorelease frequency inherit the behavior from
    /// their target queue. This is the default behavior for manually created queues.
    ///
    ///
    /// Dispatch queues with this autorelease frequency push and pop an autorelease
    /// pool around the execution of every block that was submitted to it
    /// asynchronously.
    ///
    /// See: dispatch_queue_attr_make_with_autorelease_frequency().
    ///
    ///
    /// Dispatch queues with this autorelease frequency never set up an individual
    /// autorelease pool around the execution of a block that is submitted to it
    /// asynchronously. This is the behavior of the global concurrent queues.
    #[doc(alias = "DISPATCH_AUTORELEASE_FREQUENCY_NEVER")]
    pub const NEVER: Self = Self(2);
}

#[cfg(feature = "objc2")]
unsafe impl Encode for DispatchAutoReleaseFrequency {
    const ENCODING: Encoding = Encoding::C_ULONG;
}

#[cfg(feature = "objc2")]
unsafe impl RefEncode for DispatchAutoReleaseFrequency {
    const ENCODING_REF: Encoding = Encoding::Pointer(&Self::ENCODING);
}

impl DispatchQueueAttr {
    /// Returns a dispatch queue attribute value with the autorelease frequency
    /// set to the specified value.
    ///
    ///
    /// When a queue uses the per-workitem autorelease frequency (either directly
    /// or inherited from its target queue), any block submitted asynchronously to
    /// this queue (via dispatch_async(), dispatch_barrier_async(),
    /// dispatch_group_notify(), etc...) is executed as if surrounded by a individual
    /// Objective-C
    /// <code>
    /// objc2::rc::autoreleasepool</code>
    /// scope.
    ///
    /// Autorelease frequency has no effect on blocks that are submitted
    /// synchronously to a queue (via dispatch_sync(), dispatch_barrier_sync()).
    ///
    /// The global concurrent queues have the DISPATCH_AUTORELEASE_FREQUENCY_NEVER
    /// behavior. Manually created dispatch queues use
    /// DISPATCH_AUTORELEASE_FREQUENCY_INHERIT by default.
    ///
    /// Queues created with this attribute cannot change target queues after having
    /// been activated. See dispatch_set_target_queue() and dispatch_activate().
    ///
    ///
    /// Parameter `attr`: A queue attribute value to be combined with the specified autorelease
    /// frequency or NULL.
    ///
    ///
    /// Parameter `frequency`: The requested autorelease frequency.
    ///
    ///
    /// Returns: Returns an attribute value which may be provided to dispatch_queue_create()
    /// or NULL if an invalid autorelease frequency was requested.
    /// This new value combines the attributes specified by the 'attr' parameter and
    /// the chosen autorelease frequency.
    #[doc(alias = "dispatch_queue_attr_make_with_autorelease_frequency")]
    #[must_use]
    #[inline]
    pub fn with_autorelease_frequency(
        attr: Option<&DispatchQueueAttr>,
        frequency: DispatchAutoReleaseFrequency,
    ) -> DispatchRetained<DispatchQueueAttr> {
        extern "C" {
            fn dispatch_queue_attr_make_with_autorelease_frequency(
                attr: Option<&DispatchQueueAttr>,
                frequency: DispatchAutoReleaseFrequency,
            ) -> Option<NonNull<DispatchQueueAttr>>;
        }
        let ret = unsafe { dispatch_queue_attr_make_with_autorelease_frequency(attr, frequency) };
        let ret =
            ret.expect("function was marked as returning non-null, but actually returned NULL");
        unsafe { DispatchRetained::retain(ret) }
    }

    /// Returns an attribute value which may be provided to dispatch_queue_create()
    /// or dispatch_queue_create_with_target(), in order to assign a QOS class and
    /// relative priority to the queue.
    ///
    ///
    /// When specified in this manner, the QOS class and relative priority take
    /// precedence over those inherited from the dispatch queue's target queue (if
    /// any) as long that does not result in a lower QOS class and relative priority.
    ///
    /// The global queue priorities map to the following QOS classes:
    /// - DISPATCH_QUEUE_PRIORITY_HIGH:         QOS_CLASS_USER_INITIATED
    /// - DISPATCH_QUEUE_PRIORITY_DEFAULT:      QOS_CLASS_DEFAULT
    /// - DISPATCH_QUEUE_PRIORITY_LOW:          QOS_CLASS_UTILITY
    /// - DISPATCH_QUEUE_PRIORITY_BACKGROUND:   QOS_CLASS_BACKGROUND
    ///
    /// Example:
    /// <code>
    /// dispatch_queue_t queue;
    /// dispatch_queue_attr_t attr;
    /// attr = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL,
    /// QOS_CLASS_UTILITY, 0);
    /// queue = dispatch_queue_create("com.example.myqueue", attr);
    /// </code>
    ///
    /// The QOS class and relative priority set this way on a queue have no effect on
    /// blocks that are submitted synchronously to a queue (via dispatch_sync(),
    /// dispatch_barrier_sync()).
    ///
    ///
    /// Parameter `attr`: A queue attribute value to be combined with the QOS class, or NULL.
    ///
    ///
    /// Parameter `qos_class`: A QOS class value:
    /// - QOS_CLASS_USER_INTERACTIVE
    /// - QOS_CLASS_USER_INITIATED
    /// - QOS_CLASS_DEFAULT
    /// - QOS_CLASS_UTILITY
    /// - QOS_CLASS_BACKGROUND
    /// Passing any other value results in NULL being returned.
    ///
    ///
    /// Parameter `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.
    ///
    ///
    /// Returns: Returns an attribute value which may be provided to dispatch_queue_create()
    /// and dispatch_queue_create_with_target(), or NULL if an invalid QOS class was
    /// requested.
    /// The new value combines the attributes specified by the 'attr' parameter and
    /// the new QOS class and relative priority.
    #[doc(alias = "dispatch_queue_attr_make_with_qos_class")]
    #[must_use]
    #[inline]
    pub fn with_qos_class(
        attr: Option<&DispatchQueueAttr>,
        qos_class: DispatchQoS,
        relative_priority: c_int,
    ) -> DispatchRetained<DispatchQueueAttr> {
        extern "C" {
            fn dispatch_queue_attr_make_with_qos_class(
                attr: Option<&DispatchQueueAttr>,
                qos_class: DispatchQoS,
                relative_priority: c_int,
            ) -> Option<NonNull<DispatchQueueAttr>>;
        }
        let ret =
            unsafe { dispatch_queue_attr_make_with_qos_class(attr, qos_class, relative_priority) };
        let ret =
            ret.expect("function was marked as returning non-null, but actually returned NULL");
        unsafe { DispatchRetained::retain(ret) }
    }
}

impl DispatchQueue {
    /// Creates a new dispatch queue with a specified target queue.
    ///
    ///
    /// Dispatch queues created with the DISPATCH_QUEUE_SERIAL or a NULL attribute
    /// invoke blocks serially in FIFO order.
    ///
    /// Dispatch queues created with the DISPATCH_QUEUE_CONCURRENT attribute may
    /// invoke blocks concurrently (similarly to the global concurrent queues, but
    /// potentially with more overhead), and support barrier blocks submitted with
    /// the dispatch barrier API, which e.g. enables the implementation of efficient
    /// reader-writer schemes.
    ///
    /// When a dispatch queue is no longer needed, it should be released with
    /// dispatch_release(). Note that any pending blocks submitted asynchronously to
    /// a queue will hold a reference to that queue. Therefore a queue will not be
    /// deallocated until all pending blocks have finished.
    ///
    /// When using a dispatch queue attribute
    /// _attr_specifying a QoS class (derived
    /// from the result of dispatch_queue_attr_make_with_qos_class()), passing the
    /// result of dispatch_get_global_queue() in
    /// _target_will ignore the QoS class
    /// of that global queue and will use the global queue with the QoS class
    /// specified by attr instead.
    ///
    /// Queues created with dispatch_queue_create_with_target() cannot have their
    /// target queue changed, unless created inactive (See
    /// dispatch_queue_attr_make_initially_inactive()), in which case the target
    /// queue can be changed until the newly created queue is activated with
    /// dispatch_activate().
    ///
    ///
    /// Parameter `label`: A string label to attach to the queue.
    /// This parameter is optional and may be NULL.
    ///
    ///
    /// Parameter `attr`: A predefined attribute such as DISPATCH_QUEUE_SERIAL,
    /// DISPATCH_QUEUE_CONCURRENT, or the result of a call to
    /// a dispatch_queue_attr_make_with_* function.
    ///
    ///
    /// Parameter `target`: The target queue for the newly created queue. The target queue is retained.
    /// If this parameter is DISPATCH_TARGET_QUEUE_DEFAULT, sets the queue's target
    /// queue to the default target queue for the given queue type.
    ///
    ///
    /// Returns: The newly created dispatch queue.
    #[doc(alias = "dispatch_queue_create_with_target")]
    #[must_use]
    #[inline]
    pub(crate) unsafe fn __new_with_target(
        label: *const c_char,
        attr: Option<&DispatchQueueAttr>,
        target: Option<&DispatchQueue>,
    ) -> DispatchRetained<DispatchQueue> {
        extern "C" {
            #[cfg_attr(
                target_vendor = "apple",
                link_name = "dispatch_queue_create_with_target$V2"
            )]
            fn dispatch_queue_create_with_target(
                label: *const c_char,
                attr: Option<&DispatchQueueAttr>,
                target: Option<&DispatchQueue>,
            ) -> Option<NonNull<DispatchQueue>>;
        }
        let ret = unsafe { dispatch_queue_create_with_target(label, attr, target) };
        let ret =
            ret.expect("function was marked as returning non-null, but actually returned NULL");
        unsafe { DispatchRetained::from_raw(ret) }
    }

    /// Creates a new dispatch queue to which blocks may be submitted.
    ///
    ///
    /// Dispatch queues created with the DISPATCH_QUEUE_SERIAL or a NULL attribute
    /// invoke blocks serially in FIFO order.
    ///
    /// Dispatch queues created with the DISPATCH_QUEUE_CONCURRENT attribute may
    /// invoke blocks concurrently (similarly to the global concurrent queues, but
    /// potentially with more overhead), and support barrier blocks submitted with
    /// the dispatch barrier API, which e.g. enables the implementation of efficient
    /// reader-writer schemes.
    ///
    /// When a dispatch queue is no longer needed, it should be released with
    /// dispatch_release(). Note that any pending blocks submitted asynchronously to
    /// a queue will hold a reference to that queue. Therefore a queue will not be
    /// deallocated until all pending blocks have finished.
    ///
    /// Passing the result of the dispatch_queue_attr_make_with_qos_class() function
    /// to the attr parameter of this function allows a quality of service class and
    /// relative priority to be specified for the newly created queue.
    /// The quality of service class so specified takes precedence over the quality
    /// of service class of the newly created dispatch queue's target queue (if any)
    /// as long that does not result in a lower QOS class and relative priority.
    ///
    /// When no quality of service class is specified, the target queue of a newly
    /// created dispatch queue is the default priority global concurrent queue.
    ///
    /// Unless explicitly specified via the attribute, queues are created active.
    ///
    ///
    /// Parameter `label`: A string label to attach to the queue.
    /// This parameter is optional and may be NULL.
    ///
    ///
    /// Parameter `attr`: A predefined attribute such as DISPATCH_QUEUE_SERIAL,
    /// DISPATCH_QUEUE_CONCURRENT, or the result of a call to
    /// a dispatch_queue_attr_make_with_* function.
    ///
    ///
    /// Returns: The newly created dispatch queue.
    #[doc(alias = "dispatch_queue_create")]
    #[must_use]
    #[inline]
    pub(crate) unsafe fn __new(
        label: *const c_char,
        attr: Option<&DispatchQueueAttr>,
    ) -> DispatchRetained<DispatchQueue> {
        extern "C" {
            fn dispatch_queue_create(
                label: *const c_char,
                attr: Option<&DispatchQueueAttr>,
            ) -> Option<NonNull<DispatchQueue>>;
        }
        let ret = unsafe { dispatch_queue_create(label, attr) };
        let ret =
            ret.expect("function was marked as returning non-null, but actually returned NULL");
        unsafe { DispatchRetained::from_raw(ret) }
    }

    /// Returns the label of the given queue, as specified when the queue was
    /// created, or the empty string if a NULL label was specified.
    ///
    /// Passing DISPATCH_CURRENT_QUEUE_LABEL will return the label of the current
    /// queue.
    ///
    ///
    /// Parameter `queue`: The queue to query, or DISPATCH_CURRENT_QUEUE_LABEL.
    ///
    ///
    /// Returns: The label of the queue.
    #[doc(alias = "dispatch_queue_get_label")]
    #[must_use]
    #[inline]
    pub fn label(queue: Option<&DispatchQueue>) -> NonNull<c_char> {
        extern "C" {
            fn dispatch_queue_get_label(queue: Option<&DispatchQueue>) -> Option<NonNull<c_char>>;
        }
        let ret = unsafe { dispatch_queue_get_label(queue) };
        ret.expect("function was marked as returning non-null, but actually returned NULL")
    }

    /// Returns the QOS class and relative priority of the given queue.
    ///
    ///
    /// If the given queue was created with an attribute value returned from
    /// dispatch_queue_attr_make_with_qos_class(), this function returns the QOS
    /// class and relative priority specified at that time; for any other attribute
    /// value it returns a QOS class of QOS_CLASS_UNSPECIFIED and a relative
    /// priority of 0.
    ///
    /// If the given queue is one of the global queues, this function returns its
    /// assigned QOS class value as documented under dispatch_get_global_queue() and
    /// a relative priority of 0; in the case of the main queue it returns the QOS
    /// value provided by qos_class_main() and a relative priority of 0.
    ///
    ///
    /// Parameter `queue`: The queue to query.
    ///
    ///
    /// Parameter `relative_priority_ptr`: A pointer to an int variable to be filled with the relative priority offset
    /// within the QOS class, or NULL.
    ///
    ///
    /// Returns: A QOS class value:
    /// - QOS_CLASS_USER_INTERACTIVE
    /// - QOS_CLASS_USER_INITIATED
    /// - QOS_CLASS_DEFAULT
    /// - QOS_CLASS_UTILITY
    /// - QOS_CLASS_BACKGROUND
    /// - QOS_CLASS_UNSPECIFIED
    #[doc(alias = "dispatch_queue_get_qos_class")]
    #[must_use]
    #[inline]
    pub unsafe fn qos_class(
        self: &DispatchQueue,
        relative_priority_ptr: *mut c_int,
    ) -> DispatchQoS {
        extern "C" {
            fn dispatch_queue_get_qos_class(
                queue: &DispatchQueue,
                relative_priority_ptr: *mut c_int,
            ) -> DispatchQoS;
        }
        unsafe { dispatch_queue_get_qos_class(self, relative_priority_ptr) }
    }
}

extern "C" {
    /// Sets the target queue for the given object.
    ///
    ///
    /// An object's target queue is responsible for processing the object.
    ///
    /// When no quality of service class and relative priority is specified for a
    /// dispatch queue at the time of creation, a dispatch queue's quality of service
    /// class is inherited from its target queue. The dispatch_get_global_queue()
    /// function may be used to obtain a target queue of a specific quality of
    /// service class, however the use of dispatch_queue_attr_make_with_qos_class()
    /// is recommended instead.
    ///
    /// 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 result of introducing a cycle into the hierarchy of target queues is
    /// undefined.
    ///
    /// A dispatch source's target queue specifies where its event handler and
    /// cancellation handler blocks will be submitted.
    ///
    /// A dispatch I/O channel's target queue specifies where where its I/O
    /// operations are executed. If the channel's target queue's priority is set to
    /// DISPATCH_QUEUE_PRIORITY_BACKGROUND, then the I/O operations performed by
    /// dispatch_io_read() or dispatch_io_write() on that queue will be
    /// throttled when there is I/O contention.
    ///
    /// For all other dispatch object types, the only function of the target queue
    /// is to determine where an object's finalizer function is invoked.
    ///
    /// In general, changing the target queue of an object is an asynchronous
    /// operation that doesn't take effect immediately, and doesn't affect blocks
    /// already associated with the specified object.
    ///
    /// However, if an object is inactive at the time dispatch_set_target_queue() is
    /// called, then the target queue change takes effect immediately, and will
    /// affect blocks already associated with the specified object. After an
    /// initially inactive object has been activated, calling
    /// dispatch_set_target_queue() results in an assertion and the process being
    /// terminated.
    ///
    /// If a dispatch queue is active and targeted by other dispatch objects,
    /// changing its target queue results in undefined behavior.  Instead, it is
    /// recommended to create dispatch objects in an inactive state, set up the
    /// relevant target queues and then activate them.
    ///
    ///
    /// Parameter `object`: The object to modify.
    /// The result of passing NULL in this parameter is undefined.
    ///
    ///
    /// Parameter `queue`: The new target queue for the object. The queue is retained, and the
    /// previous target queue, if any, is released.
    /// If queue is DISPATCH_TARGET_QUEUE_DEFAULT, set the object's target queue
    /// to the default target queue for the given object type.
    pub fn dispatch_set_target_queue(
        object: NonNull<dispatch_object_s>,
        queue: Option<&DispatchQueue>,
    );
}

impl DispatchQueue {
    #[doc(alias = "dispatch_after")]
    #[cfg(feature = "block2")]
    #[inline]
    pub unsafe fn exec_after_with_block(
        when: DispatchTime,
        queue: &DispatchQueue,
        block: dispatch_block_t,
    ) {
        extern "C" {
            fn dispatch_after(when: DispatchTime, queue: &DispatchQueue, block: dispatch_block_t);
        }
        unsafe { dispatch_after(when, queue, block) }
    }

    /// Schedule a function for execution on a given queue at a specified time.
    ///
    ///
    /// See dispatch_after() for details.
    ///
    ///
    /// Parameter `when`: A temporal milestone returned by dispatch_time() or dispatch_walltime().
    ///
    ///
    /// Parameter `queue`: A queue to which the given function will be submitted at the specified time.
    /// The result of passing NULL in this parameter is undefined.
    ///
    ///
    /// Parameter `context`: The application-defined context parameter to pass to the function.
    ///
    ///
    /// Parameter `work`: The application-defined function to invoke on the target queue. The first
    /// parameter passed to this function is the context provided to
    /// dispatch_after_f().
    /// The result of passing NULL in this parameter is undefined.
    #[doc(alias = "dispatch_after_f")]
    #[inline]
    pub unsafe fn exec_after_f(
        when: DispatchTime,
        queue: &DispatchQueue,
        context: *mut c_void,
        work: dispatch_function_t,
    ) {
        extern "C" {
            fn dispatch_after_f(
                when: DispatchTime,
                queue: &DispatchQueue,
                context: *mut c_void,
                work: dispatch_function_t,
            );
        }
        unsafe { dispatch_after_f(when, queue, context, work) }
    }

    #[doc(alias = "dispatch_barrier_async")]
    #[cfg(feature = "block2")]
    #[inline]
    pub unsafe fn barrier_async_with_block(self: &DispatchQueue, block: dispatch_block_t) {
        extern "C" {
            fn dispatch_barrier_async(queue: &DispatchQueue, block: dispatch_block_t);
        }
        unsafe { dispatch_barrier_async(self, block) }
    }

    /// Submits a barrier function for asynchronous execution on a dispatch queue.
    ///
    ///
    /// Submits a function to a dispatch queue like dispatch_async_f(), but marks
    /// that function as a barrier (relevant only on DISPATCH_QUEUE_CONCURRENT
    /// queues).
    ///
    /// See dispatch_async_f() for details and "Dispatch Barrier API" for a
    /// description of the barrier semantics.
    ///
    ///
    /// Parameter `queue`: The target dispatch queue to which the function is submitted.
    /// The system will hold a reference on the target queue until the function
    /// has returned.
    /// The result of passing NULL in this parameter is undefined.
    ///
    ///
    /// Parameter `context`: The application-defined context parameter to pass to the function.
    ///
    ///
    /// Parameter `work`: The application-defined function to invoke on the target queue. The first
    /// parameter passed to this function is the context provided to
    /// dispatch_barrier_async_f().
    /// The result of passing NULL in this parameter is undefined.
    #[doc(alias = "dispatch_barrier_async_f")]
    #[inline]
    pub unsafe fn barrier_async_f(
        self: &DispatchQueue,
        context: *mut c_void,
        work: dispatch_function_t,
    ) {
        extern "C" {
            fn dispatch_barrier_async_f(
                queue: &DispatchQueue,
                context: *mut c_void,
                work: dispatch_function_t,
            );
        }
        unsafe { dispatch_barrier_async_f(self, context, work) }
    }

    #[doc(alias = "dispatch_barrier_sync")]
    #[cfg(feature = "block2")]
    #[inline]
    pub unsafe fn barrier_sync_with_block(self: &DispatchQueue, block: dispatch_block_t) {
        extern "C" {
            fn dispatch_barrier_sync(queue: &DispatchQueue, block: dispatch_block_t);
        }
        unsafe { dispatch_barrier_sync(self, block) }
    }

    /// Submits a barrier function for synchronous execution on a dispatch queue.
    ///
    ///
    /// Submits a function to a dispatch queue like dispatch_sync_f(), but marks that
    /// fuction as a barrier (relevant only on DISPATCH_QUEUE_CONCURRENT queues).
    ///
    /// See dispatch_sync_f() for details.
    ///
    ///
    /// Parameter `queue`: The target dispatch queue to which the function is submitted.
    /// The result of passing NULL in this parameter is undefined.
    ///
    ///
    /// Parameter `context`: The application-defined context parameter to pass to the function.
    ///
    ///
    /// Parameter `work`: The application-defined function to invoke on the target queue. The first
    /// parameter passed to this function is the context provided to
    /// dispatch_barrier_sync_f().
    /// The result of passing NULL in this parameter is undefined.
    #[doc(alias = "dispatch_barrier_sync_f")]
    #[inline]
    pub unsafe fn barrier_sync_f(
        self: &DispatchQueue,
        context: *mut c_void,
        work: dispatch_function_t,
    ) {
        extern "C" {
            fn dispatch_barrier_sync_f(
                queue: &DispatchQueue,
                context: *mut c_void,
                work: dispatch_function_t,
            );
        }
        unsafe { dispatch_barrier_sync_f(self, context, work) }
    }

    #[doc(alias = "dispatch_barrier_async_and_wait")]
    #[cfg(feature = "block2")]
    #[inline]
    pub unsafe fn barrier_async_and_wait_with_block(self: &DispatchQueue, block: dispatch_block_t) {
        extern "C" {
            fn dispatch_barrier_async_and_wait(queue: &DispatchQueue, block: dispatch_block_t);
        }
        unsafe { dispatch_barrier_async_and_wait(self, block) }
    }

    /// Submits a function for synchronous execution on a dispatch queue.
    ///
    ///
    /// Submits a function to a dispatch queue like dispatch_async_and_wait_f(), but
    /// marks that function as a barrier (relevant only on DISPATCH_QUEUE_CONCURRENT
    /// queues).
    ///
    /// See "Dispatch Barrier API" for a description of the barrier semantics.
    ///
    ///
    /// Parameter `queue`: The target dispatch queue to which the function is submitted.
    /// The result of passing NULL in this parameter is undefined.
    ///
    ///
    /// Parameter `context`: The application-defined context parameter to pass to the function.
    ///
    ///
    /// Parameter `work`: The application-defined function to invoke on the target queue. The first
    /// parameter passed to this function is the context provided to
    /// dispatch_barrier_async_and_wait_f().
    /// The result of passing NULL in this parameter is undefined.
    #[doc(alias = "dispatch_barrier_async_and_wait_f")]
    #[inline]
    pub unsafe fn barrier_async_and_wait_f(
        self: &DispatchQueue,
        context: *mut c_void,
        work: dispatch_function_t,
    ) {
        extern "C" {
            fn dispatch_barrier_async_and_wait_f(
                queue: &DispatchQueue,
                context: *mut c_void,
                work: dispatch_function_t,
            );
        }
        unsafe { dispatch_barrier_async_and_wait_f(self, context, work) }
    }
}

extern "C" {
    /// Associates a subsystem-specific context with a dispatch queue, for a key
    /// unique to the subsystem.
    ///
    ///
    /// The specified destructor will be invoked with the context on the default
    /// priority global concurrent queue when a new context is set for the same key,
    /// or after all references to the queue have been released.
    ///
    ///
    /// Parameter `queue`: The dispatch queue to modify.
    /// The result of passing NULL in this parameter is undefined.
    ///
    ///
    /// Parameter `key`: The key to set the context for, typically a pointer to a static variable
    /// specific to the subsystem. Keys are only compared as pointers and never
    /// dereferenced. Passing a string constant directly is not recommended.
    /// The NULL key is reserved and attempts to set a context for it are ignored.
    ///
    ///
    /// Parameter `context`: The new subsystem-specific context for the object. This may be NULL.
    ///
    ///
    /// Parameter `destructor`: The destructor function pointer. This may be NULL and is ignored if context
    /// is NULL.
    pub fn dispatch_queue_set_specific(
        queue: &DispatchQueue,
        key: NonNull<c_void>,
        context: *mut c_void,
        destructor: dispatch_function_t,
    );
}

impl DispatchQueue {
    /// Returns the subsystem-specific context associated with a dispatch queue, for
    /// a key unique to the subsystem.
    ///
    ///
    /// Returns the context for the specified key if it has been set on the specified
    /// queue.
    ///
    ///
    /// Parameter `queue`: The dispatch queue to query.
    /// The result of passing NULL in this parameter is undefined.
    ///
    ///
    /// Parameter `key`: The key to get the context for, typically a pointer to a static variable
    /// specific to the subsystem. Keys are only compared as pointers and never
    /// dereferenced. Passing a string constant directly is not recommended.
    ///
    ///
    /// Returns: The context for the specified key or NULL if no context was found.
    #[doc(alias = "dispatch_queue_get_specific")]
    #[must_use]
    #[inline]
    pub unsafe fn specific(self: &DispatchQueue, key: NonNull<c_void>) -> *mut c_void {
        extern "C" {
            fn dispatch_queue_get_specific(
                queue: &DispatchQueue,
                key: NonNull<c_void>,
            ) -> *mut c_void;
        }
        unsafe { dispatch_queue_get_specific(self, key) }
    }
}

extern "C" {
    /// Returns the current subsystem-specific context for a key unique to the
    /// subsystem.
    ///
    ///
    /// When called from a block executing on a queue, returns the context for the
    /// specified key if it has been set on the queue, otherwise returns the result
    /// of dispatch_get_specific() executed on the queue's target queue or NULL
    /// if the current queue is a global concurrent queue.
    ///
    ///
    /// Parameter `key`: The key to get the context for, typically a pointer to a static variable
    /// specific to the subsystem. Keys are only compared as pointers and never
    /// dereferenced. Passing a string constant directly is not recommended.
    ///
    ///
    /// Returns: The context for the specified key or NULL if no context was found.
    #[must_use]
    pub fn dispatch_get_specific(key: NonNull<c_void>) -> *mut c_void;
}

impl DispatchQueue {
    /// Verifies that the current block is executing on a given dispatch queue.
    ///
    ///
    /// Some code expects to be run on a specific dispatch queue. This function
    /// verifies that that expectation is true.
    ///
    /// If the currently executing block was submitted to the specified queue or to
    /// any queue targeting it (see dispatch_set_target_queue()), this function
    /// returns.
    ///
    /// If the currently executing block was submitted with a synchronous API
    /// (dispatch_sync(), dispatch_barrier_sync(), ...), the context of the
    /// submitting block is also evaluated (recursively).
    /// If a synchronously submitting block is found that was itself submitted to
    /// the specified queue or to any queue targeting it, this function returns.
    ///
    /// Otherwise this function asserts: it logs an explanation to the system log and
    /// terminates the application.
    ///
    /// Passing the result of dispatch_get_main_queue() to this function verifies
    /// that the current block was submitted to the main queue, or to a queue
    /// targeting it, or is running on the main thread (in any context).
    ///
    /// When dispatch_assert_queue() is called outside of the context of a
    /// submitted block (for example from the context of a thread created manually
    /// with pthread_create()) then this function will also assert and terminate
    /// the application.
    ///
    /// The variant dispatch_assert_queue_debug() is compiled out when the
    /// preprocessor macro NDEBUG is defined. (See also assert(3)).
    ///
    ///
    /// Parameter `queue`: The dispatch queue that the current block is expected to run on.
    /// The result of passing NULL in this parameter is undefined.
    #[doc(alias = "dispatch_assert_queue")]
    #[inline]
    pub fn assert(self: &DispatchQueue) {
        extern "C-unwind" {
            #[cfg_attr(target_vendor = "apple", link_name = "dispatch_assert_queue$V2")]
            fn dispatch_assert_queue(queue: &DispatchQueue);
        }
        unsafe { dispatch_assert_queue(self) }
    }

    /// Verifies that the current block is executing on a given dispatch queue,
    /// and that the block acts as a barrier on that queue.
    ///
    ///
    /// This behaves exactly like dispatch_assert_queue(), with the additional check
    /// that the current block acts as a barrier on the specified queue, which is
    /// always true if the specified queue is serial (see DISPATCH_BLOCK_BARRIER or
    /// dispatch_barrier_async() for details).
    ///
    /// The variant dispatch_assert_queue_barrier_debug() is compiled out when the
    /// preprocessor macro NDEBUG is defined. (See also assert()).
    ///
    ///
    /// Parameter `queue`: The dispatch queue that the current block is expected to run as a barrier on.
    /// The result of passing NULL in this parameter is undefined.
    #[doc(alias = "dispatch_assert_queue_barrier")]
    #[inline]
    pub fn assert_barrier(self: &DispatchQueue) {
        extern "C-unwind" {
            fn dispatch_assert_queue_barrier(queue: &DispatchQueue);
        }
        unsafe { dispatch_assert_queue_barrier(self) }
    }

    /// Verifies that the current block is not executing on a given dispatch queue.
    ///
    ///
    /// This function is the equivalent of dispatch_assert_queue() with the test for
    /// equality inverted. That means that it will terminate the application when
    /// dispatch_assert_queue() would return, and vice-versa. See discussion there.
    ///
    /// The variant dispatch_assert_queue_not_debug() is compiled out when the
    /// preprocessor macro NDEBUG is defined. (See also assert(3)).
    ///
    ///
    /// Parameter `queue`: The dispatch queue that the current block is expected not to run on.
    /// The result of passing NULL in this parameter is undefined.
    #[doc(alias = "dispatch_assert_queue_not")]
    #[inline]
    pub fn assert_not(self: &DispatchQueue) {
        extern "C-unwind" {
            #[cfg_attr(target_vendor = "apple", link_name = "dispatch_assert_queue_not$V2")]
            fn dispatch_assert_queue_not(queue: &DispatchQueue);
        }
        unsafe { dispatch_assert_queue_not(self) }
    }
}

extern "C-unwind" {
    pub fn dispatch_allow_send_signals(preserve_signum: c_int) -> c_int;
}

/// Flags to pass to the dispatch_block_create* functions.
///
///
/// 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.
///
///
/// Flag indicating that a dispatch block object should execute disassociated
/// from current execution context attributes such as os_activity_t
/// and properties of the current IPC request (if any). With regard to QoS class,
/// the behavior is the same as for DISPATCH_BLOCK_NO_QOS. If invoked directly,
/// the block object will remove the other 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).
///
///
/// 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.
///
///
/// 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().
///
///
/// 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.
///
///
/// 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.
///
/// See also [Apple's documentation](https://developer.apple.com/documentation/dispatch/dispatch_block_flags_t?language=objc)
// NS_OPTIONS
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct dispatch_block_flags_t(pub c_ulong);
bitflags::bitflags! {
    impl dispatch_block_flags_t: c_ulong {
/// Flags to pass to the dispatch_block_create* functions.
///
///
/// 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.
///
///
/// Flag indicating that a dispatch block object should execute disassociated
/// from current execution context attributes such as os_activity_t
/// and properties of the current IPC request (if any). With regard to QoS class,
/// the behavior is the same as for DISPATCH_BLOCK_NO_QOS. If invoked directly,
/// the block object will remove the other 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).
///
///
/// 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.
///
///
/// 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().
///
///
/// 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.
///
///
/// 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.
        const DISPATCH_BLOCK_BARRIER = 0x1;
/// Flags to pass to the dispatch_block_create* functions.
///
///
/// 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.
///
///
/// Flag indicating that a dispatch block object should execute disassociated
/// from current execution context attributes such as os_activity_t
/// and properties of the current IPC request (if any). With regard to QoS class,
/// the behavior is the same as for DISPATCH_BLOCK_NO_QOS. If invoked directly,
/// the block object will remove the other 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).
///
///
/// 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.
///
///
/// 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().
///
///
/// 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.
///
///
/// 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.
        const DISPATCH_BLOCK_DETACHED = 0x2;
/// Flags to pass to the dispatch_block_create* functions.
///
///
/// 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.
///
///
/// Flag indicating that a dispatch block object should execute disassociated
/// from current execution context attributes such as os_activity_t
/// and properties of the current IPC request (if any). With regard to QoS class,
/// the behavior is the same as for DISPATCH_BLOCK_NO_QOS. If invoked directly,
/// the block object will remove the other 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).
///
///
/// 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.
///
///
/// 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().
///
///
/// 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.
///
///
/// 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.
        const DISPATCH_BLOCK_ASSIGN_CURRENT = 0x4;
/// Flags to pass to the dispatch_block_create* functions.
///
///
/// 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.
///
///
/// Flag indicating that a dispatch block object should execute disassociated
/// from current execution context attributes such as os_activity_t
/// and properties of the current IPC request (if any). With regard to QoS class,
/// the behavior is the same as for DISPATCH_BLOCK_NO_QOS. If invoked directly,
/// the block object will remove the other 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).
///
///
/// 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.
///
///
/// 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().
///
///
/// 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.
///
///
/// 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.
        const DISPATCH_BLOCK_NO_QOS_CLASS = 0x8;
/// Flags to pass to the dispatch_block_create* functions.
///
///
/// 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.
///
///
/// Flag indicating that a dispatch block object should execute disassociated
/// from current execution context attributes such as os_activity_t
/// and properties of the current IPC request (if any). With regard to QoS class,
/// the behavior is the same as for DISPATCH_BLOCK_NO_QOS. If invoked directly,
/// the block object will remove the other 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).
///
///
/// 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.
///
///
/// 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().
///
///
/// 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.
///
///
/// 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.
        const DISPATCH_BLOCK_INHERIT_QOS_CLASS = 0x10;
/// Flags to pass to the dispatch_block_create* functions.
///
///
/// 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.
///
///
/// Flag indicating that a dispatch block object should execute disassociated
/// from current execution context attributes such as os_activity_t
/// and properties of the current IPC request (if any). With regard to QoS class,
/// the behavior is the same as for DISPATCH_BLOCK_NO_QOS. If invoked directly,
/// the block object will remove the other 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).
///
///
/// 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.
///
///
/// 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().
///
///
/// 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.
///
///
/// 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.
        const DISPATCH_BLOCK_ENFORCE_QOS_CLASS = 0x20;
    }
}

#[cfg(feature = "objc2")]
unsafe impl Encode for dispatch_block_flags_t {
    const ENCODING: Encoding = Encoding::C_ULONG;
}

#[cfg(feature = "objc2")]
unsafe impl RefEncode for dispatch_block_flags_t {
    const ENCODING_REF: Encoding = Encoding::Pointer(&Self::ENCODING);
}

extern "C" {
    /// Create a new dispatch block object on the heap from an existing block and
    /// the given flags.
    ///
    ///
    /// 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.
    ///
    ///
    /// Parameter `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.
    ///
    ///
    /// Parameter `block`: The block to create the dispatch block object from.
    ///
    ///
    /// Returns: 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.
    #[cfg(feature = "block2")]
    #[must_use]
    pub fn dispatch_block_create(
        flags: dispatch_block_flags_t,
        block: dispatch_block_t,
    ) -> dispatch_block_t;
}

extern "C" {
    /// 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.
    ///
    ///
    /// 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.
    ///
    ///
    /// Parameter `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.
    ///
    ///
    /// Parameter `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.
    ///
    ///
    /// Parameter `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.
    ///
    ///
    /// Parameter `block`: The block to create the dispatch block object from.
    ///
    ///
    /// Returns: 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.
    #[cfg(feature = "block2")]
    #[must_use]
    pub fn dispatch_block_create_with_qos_class(
        flags: dispatch_block_flags_t,
        qos_class: DispatchQoS,
        relative_priority: c_int,
        block: dispatch_block_t,
    ) -> dispatch_block_t;
}

extern "C" {
    /// Create, synchronously execute and release a dispatch block object from the
    /// specified block and flags.
    ///
    ///
    /// 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.
    ///
    ///
    /// Parameter `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.
    ///
    ///
    /// Parameter `block`: The block to create the temporary block object from.
    #[cfg(feature = "block2")]
    pub fn dispatch_block_perform(flags: dispatch_block_flags_t, block: dispatch_block_t);
}

extern "C" {
    /// Wait synchronously until execution of the specified dispatch block object has
    /// completed or until the specified timeout has elapsed.
    ///
    ///
    /// 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().
    ///
    ///
    /// Parameter `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.
    ///
    ///
    /// Parameter `timeout`: When to timeout (see dispatch_time). As a convenience, there are the
    /// DISPATCH_TIME_NOW and DISPATCH_TIME_FOREVER constants.
    ///
    ///
    /// Returns: Returns zero on success (the dispatch block object completed within the
    /// specified timeout) or non-zero on error (i.e. timed out).
    #[cfg(feature = "block2")]
    pub fn dispatch_block_wait(block: dispatch_block_t, timeout: DispatchTime) -> isize;
}

extern "C" {
    /// Schedule a notification block to be submitted to a queue when the execution
    /// of a specified dispatch block object has completed.
    ///
    ///
    /// 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.
    ///
    ///
    /// Parameter `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.
    ///
    ///
    /// Parameter `queue`: The queue to which the supplied notification block will be submitted when
    /// the observed block completes.
    ///
    ///
    /// Parameter `notification_block`: The notification block to submit when the observed block object completes.
    #[cfg(feature = "block2")]
    pub fn dispatch_block_notify(
        block: dispatch_block_t,
        queue: &DispatchQueue,
        notification_block: dispatch_block_t,
    );
}

extern "C" {
    /// Asynchronously cancel the specified dispatch block object.
    ///
    ///
    /// 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.
    ///
    ///
    /// Parameter `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.
    #[cfg(feature = "block2")]
    pub fn dispatch_block_cancel(block: dispatch_block_t);
}

extern "C" {
    /// Tests whether the given dispatch block object has been canceled.
    ///
    ///
    /// Parameter `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.
    ///
    ///
    /// Returns: Non-zero if canceled and zero if not canceled.
    #[cfg(feature = "block2")]
    #[must_use]
    pub fn dispatch_block_testcancel(block: dispatch_block_t) -> isize;
}

extern "C" {
    /// [Apple's documentation](https://developer.apple.com/documentation/dispatch/_dispatch_source_type_data_add?language=objc)
    pub static _dispatch_source_type_data_add: dispatch_source_type_s;
}

extern "C" {
    /// [Apple's documentation](https://developer.apple.com/documentation/dispatch/_dispatch_source_type_data_or?language=objc)
    pub static _dispatch_source_type_data_or: dispatch_source_type_s;
}

extern "C" {
    /// [Apple's documentation](https://developer.apple.com/documentation/dispatch/_dispatch_source_type_data_replace?language=objc)
    pub static _dispatch_source_type_data_replace: dispatch_source_type_s;
}

extern "C" {
    /// [Apple's documentation](https://developer.apple.com/documentation/dispatch/_dispatch_source_type_mach_send?language=objc)
    pub static _dispatch_source_type_mach_send: dispatch_source_type_s;
}

extern "C" {
    /// [Apple's documentation](https://developer.apple.com/documentation/dispatch/_dispatch_source_type_mach_recv?language=objc)
    pub static _dispatch_source_type_mach_recv: dispatch_source_type_s;
}

extern "C" {
    /// [Apple's documentation](https://developer.apple.com/documentation/dispatch/_dispatch_source_type_memorypressure?language=objc)
    pub static _dispatch_source_type_memorypressure: dispatch_source_type_s;
}

extern "C" {
    /// [Apple's documentation](https://developer.apple.com/documentation/dispatch/_dispatch_source_type_proc?language=objc)
    pub static _dispatch_source_type_proc: dispatch_source_type_s;
}

extern "C" {
    /// [Apple's documentation](https://developer.apple.com/documentation/dispatch/_dispatch_source_type_read?language=objc)
    pub static _dispatch_source_type_read: dispatch_source_type_s;
}

extern "C" {
    /// [Apple's documentation](https://developer.apple.com/documentation/dispatch/_dispatch_source_type_signal?language=objc)
    pub static _dispatch_source_type_signal: dispatch_source_type_s;
}

extern "C" {
    /// [Apple's documentation](https://developer.apple.com/documentation/dispatch/_dispatch_source_type_timer?language=objc)
    pub static _dispatch_source_type_timer: dispatch_source_type_s;
}

extern "C" {
    /// [Apple's documentation](https://developer.apple.com/documentation/dispatch/_dispatch_source_type_vnode?language=objc)
    pub static _dispatch_source_type_vnode: dispatch_source_type_s;
}

extern "C" {
    /// [Apple's documentation](https://developer.apple.com/documentation/dispatch/_dispatch_source_type_write?language=objc)
    pub static _dispatch_source_type_write: dispatch_source_type_s;
}

impl DispatchSource {
    /// Creates a new dispatch source to monitor low-level system objects and auto-
    /// matically submit a handler block to a dispatch queue in response to events.
    ///
    ///
    /// Dispatch sources are not reentrant. Any events received while the dispatch
    /// source is suspended or while the event handler block is currently executing
    /// will be coalesced and delivered after the dispatch source is resumed or the
    /// event handler block has returned.
    ///
    /// Dispatch sources are created in an inactive state. After creating the
    /// source and setting any desired attributes (i.e. the handler, context, etc.),
    /// a call must be made to dispatch_activate() in order to begin event delivery.
    ///
    /// A source must have been activated before being disposed.
    ///
    /// Calling dispatch_set_target_queue() on a source once it has been activated
    /// is not allowed (see dispatch_activate() and dispatch_set_target_queue()).
    ///
    /// For backward compatibility reasons, dispatch_resume() on an inactive,
    /// and not otherwise suspended source has the same effect as calling
    /// dispatch_activate(). For new code, using dispatch_activate() is preferred.
    ///
    ///
    /// Parameter `type`: Declares the type of the dispatch source. Must be one of the defined
    /// dispatch_source_type_t constants.
    ///
    ///
    /// Parameter `handle`: The underlying system handle to monitor. The interpretation of this argument
    /// is determined by the constant provided in the type parameter.
    ///
    ///
    /// Parameter `mask`: A mask of flags specifying which events are desired. The interpretation of
    /// this argument is determined by the constant provided in the type parameter.
    ///
    ///
    /// Parameter `queue`: The dispatch queue to which the event handler block will be submitted.
    /// If queue is DISPATCH_TARGET_QUEUE_DEFAULT, the source will submit the event
    /// handler block to the default priority global queue.
    ///
    ///
    /// Returns: The newly created dispatch source. Or NULL if invalid arguments are passed.
    #[doc(alias = "dispatch_source_create")]
    #[must_use]
    #[inline]
    pub unsafe fn new(
        r#type: dispatch_source_type_t,
        handle: usize,
        mask: usize,
        queue: Option<&DispatchQueue>,
    ) -> DispatchRetained<DispatchSource> {
        extern "C" {
            fn dispatch_source_create(
                r#type: dispatch_source_type_t,
                handle: usize,
                mask: usize,
                queue: Option<&DispatchQueue>,
            ) -> Option<NonNull<DispatchSource>>;
        }
        let ret = unsafe { dispatch_source_create(r#type, handle, mask, queue) };
        let ret =
            ret.expect("function was marked as returning non-null, but actually returned NULL");
        unsafe { DispatchRetained::from_raw(ret) }
    }

    #[doc(alias = "dispatch_source_set_event_handler")]
    #[cfg(feature = "block2")]
    #[inline]
    pub unsafe fn set_event_handler_with_block(self: &DispatchSource, handler: dispatch_block_t) {
        extern "C" {
            fn dispatch_source_set_event_handler(
                source: &DispatchSource,
                handler: dispatch_block_t,
            );
        }
        unsafe { dispatch_source_set_event_handler(self, handler) }
    }

    /// Sets the event handler function for the given dispatch source.
    ///
    ///
    /// Parameter `source`: The dispatch source to modify.
    /// The result of passing NULL in this parameter is undefined.
    ///
    ///
    /// Parameter `handler`: The event handler function to submit to the source's target queue.
    /// The context parameter passed to the event handler function is the context of
    /// the dispatch source current at the time the event handler was set.
    #[doc(alias = "dispatch_source_set_event_handler_f")]
    #[inline]
    pub fn set_event_handler_f(self: &DispatchSource, handler: dispatch_function_t) {
        extern "C" {
            fn dispatch_source_set_event_handler_f(
                source: &DispatchSource,
                handler: dispatch_function_t,
            );
        }
        unsafe { dispatch_source_set_event_handler_f(self, handler) }
    }

    #[doc(alias = "dispatch_source_set_cancel_handler")]
    #[cfg(feature = "block2")]
    #[inline]
    pub unsafe fn set_cancel_handler_with_block(self: &DispatchSource, handler: dispatch_block_t) {
        extern "C" {
            fn dispatch_source_set_cancel_handler(
                source: &DispatchSource,
                handler: dispatch_block_t,
            );
        }
        unsafe { dispatch_source_set_cancel_handler(self, handler) }
    }

    /// Sets the cancellation handler function for the given dispatch source.
    ///
    ///
    /// See dispatch_source_set_cancel_handler() for more details.
    ///
    ///
    /// Parameter `source`: The dispatch source to modify.
    /// The result of passing NULL in this parameter is undefined.
    ///
    ///
    /// Parameter `handler`: The cancellation handler function to submit to the source's target queue.
    /// The context parameter passed to the event handler function is the current
    /// context of the dispatch source at the time the handler call is made.
    #[doc(alias = "dispatch_source_set_cancel_handler_f")]
    #[inline]
    pub fn set_cancel_handler_f(self: &DispatchSource, handler: dispatch_function_t) {
        extern "C" {
            fn dispatch_source_set_cancel_handler_f(
                source: &DispatchSource,
                handler: dispatch_function_t,
            );
        }
        unsafe { dispatch_source_set_cancel_handler_f(self, handler) }
    }

    /// Asynchronously cancel the dispatch source, preventing any further invocation
    /// of its event handler block.
    ///
    ///
    /// Cancellation prevents any further invocation of the event handler block for
    /// the specified dispatch source, but does not interrupt an event handler
    /// block that is already in progress.
    ///
    /// The cancellation handler is submitted to the source's target queue once the
    /// the source's event handler has finished, indicating it is now safe to close
    /// the source's handle (i.e. file descriptor or mach port).
    ///
    /// See dispatch_source_set_cancel_handler() for more information.
    ///
    ///
    /// Parameter `source`: The dispatch source to be canceled.
    /// The result of passing NULL in this parameter is undefined.
    #[doc(alias = "dispatch_source_cancel")]
    #[inline]
    pub fn cancel(self: &DispatchSource) {
        extern "C" {
            fn dispatch_source_cancel(source: &DispatchSource);
        }
        unsafe { dispatch_source_cancel(self) }
    }

    /// Tests whether the given dispatch source has been canceled.
    ///
    ///
    /// Parameter `source`: The dispatch source to be tested.
    /// The result of passing NULL in this parameter is undefined.
    ///
    ///
    /// Returns: Non-zero if canceled and zero if not canceled.
    #[doc(alias = "dispatch_source_testcancel")]
    #[must_use]
    #[inline]
    pub fn testcancel(self: &DispatchSource) -> isize {
        extern "C" {
            fn dispatch_source_testcancel(source: &DispatchSource) -> isize;
        }
        unsafe { dispatch_source_testcancel(self) }
    }

    /// Returns the underlying system handle associated with this dispatch source.
    ///
    ///
    /// Parameter `source`: The result of passing NULL in this parameter is undefined.
    ///
    ///
    /// Returns: The return value should be interpreted according to the type of the dispatch
    /// source, and may be one of the following handles:
    ///
    /// DISPATCH_SOURCE_TYPE_DATA_ADD:        n/a
    /// DISPATCH_SOURCE_TYPE_DATA_OR:         n/a
    /// DISPATCH_SOURCE_TYPE_DATA_REPLACE:    n/a
    /// DISPATCH_SOURCE_TYPE_MACH_SEND:       mach port (mach_port_t)
    /// DISPATCH_SOURCE_TYPE_MACH_RECV:       mach port (mach_port_t)
    /// DISPATCH_SOURCE_TYPE_MEMORYPRESSURE   n/a
    /// DISPATCH_SOURCE_TYPE_PROC:            process identifier (pid_t)
    /// DISPATCH_SOURCE_TYPE_READ:            file descriptor (int)
    /// DISPATCH_SOURCE_TYPE_SIGNAL:          signal number (int)
    /// DISPATCH_SOURCE_TYPE_TIMER:           n/a
    /// DISPATCH_SOURCE_TYPE_VNODE:           file descriptor (int)
    /// DISPATCH_SOURCE_TYPE_WRITE:           file descriptor (int)
    #[doc(alias = "dispatch_source_get_handle")]
    #[must_use]
    #[inline]
    pub fn handle(self: &DispatchSource) -> usize {
        extern "C" {
            fn dispatch_source_get_handle(source: &DispatchSource) -> usize;
        }
        unsafe { dispatch_source_get_handle(self) }
    }

    /// Returns the mask of events monitored by the dispatch source.
    ///
    ///
    /// Parameter `source`: The result of passing NULL in this parameter is undefined.
    ///
    ///
    /// Returns: The return value should be interpreted according to the type of the dispatch
    /// source, and may be one of the following flag sets:
    ///
    /// DISPATCH_SOURCE_TYPE_DATA_ADD:        n/a
    /// DISPATCH_SOURCE_TYPE_DATA_OR:         n/a
    /// DISPATCH_SOURCE_TYPE_DATA_REPLACE:    n/a
    /// DISPATCH_SOURCE_TYPE_MACH_SEND:       dispatch_source_mach_send_flags_t
    /// DISPATCH_SOURCE_TYPE_MACH_RECV:       dispatch_source_mach_recv_flags_t
    /// DISPATCH_SOURCE_TYPE_MEMORYPRESSURE   dispatch_source_memorypressure_flags_t
    /// DISPATCH_SOURCE_TYPE_PROC:            dispatch_source_proc_flags_t
    /// DISPATCH_SOURCE_TYPE_READ:            n/a
    /// DISPATCH_SOURCE_TYPE_SIGNAL:          n/a
    /// DISPATCH_SOURCE_TYPE_TIMER:           dispatch_source_timer_flags_t
    /// DISPATCH_SOURCE_TYPE_VNODE:           dispatch_source_vnode_flags_t
    /// DISPATCH_SOURCE_TYPE_WRITE:           n/a
    #[doc(alias = "dispatch_source_get_mask")]
    #[must_use]
    #[inline]
    pub fn mask(self: &DispatchSource) -> usize {
        extern "C" {
            fn dispatch_source_get_mask(source: &DispatchSource) -> usize;
        }
        unsafe { dispatch_source_get_mask(self) }
    }

    /// Returns pending data for the dispatch source.
    ///
    ///
    /// This function is intended to be called from within the event handler block.
    /// The result of calling this function outside of the event handler callback is
    /// undefined.
    ///
    ///
    /// Parameter `source`: The result of passing NULL in this parameter is undefined.
    ///
    ///
    /// Returns: The return value should be interpreted according to the type of the dispatch
    /// source, and may be one of the following:
    ///
    /// DISPATCH_SOURCE_TYPE_DATA_ADD:        application defined data
    /// DISPATCH_SOURCE_TYPE_DATA_OR:         application defined data
    /// DISPATCH_SOURCE_TYPE_DATA_REPLACE:    application defined data
    /// DISPATCH_SOURCE_TYPE_MACH_SEND:       dispatch_source_mach_send_flags_t
    /// DISPATCH_SOURCE_TYPE_MACH_RECV:       dispatch_source_mach_recv_flags_t
    /// DISPATCH_SOURCE_TYPE_MEMORYPRESSURE   dispatch_source_memorypressure_flags_t
    /// DISPATCH_SOURCE_TYPE_PROC:            dispatch_source_proc_flags_t
    /// DISPATCH_SOURCE_TYPE_READ:            estimated bytes available to read
    /// DISPATCH_SOURCE_TYPE_SIGNAL:          number of signals delivered since
    /// the last handler invocation
    /// DISPATCH_SOURCE_TYPE_TIMER:           number of times the timer has fired
    /// since the last handler invocation
    /// DISPATCH_SOURCE_TYPE_VNODE:           dispatch_source_vnode_flags_t
    /// DISPATCH_SOURCE_TYPE_WRITE:           estimated buffer space available
    #[doc(alias = "dispatch_source_get_data")]
    #[must_use]
    #[inline]
    pub fn data(self: &DispatchSource) -> usize {
        extern "C" {
            fn dispatch_source_get_data(source: &DispatchSource) -> usize;
        }
        unsafe { dispatch_source_get_data(self) }
    }

    /// Merges data into a dispatch source of type DISPATCH_SOURCE_TYPE_DATA_ADD,
    /// DISPATCH_SOURCE_TYPE_DATA_OR or DISPATCH_SOURCE_TYPE_DATA_REPLACE,
    /// and submits its event handler block to its target queue.
    ///
    ///
    /// Parameter `source`: The result of passing NULL in this parameter is undefined.
    ///
    ///
    /// Parameter `value`: The value to coalesce with the pending data using a logical OR or an ADD
    /// as specified by the dispatch source type. A value of zero has no effect
    /// and will not result in the submission of the event handler block.
    #[doc(alias = "dispatch_source_merge_data")]
    #[inline]
    pub fn merge_data(self: &DispatchSource, value: usize) {
        extern "C" {
            fn dispatch_source_merge_data(source: &DispatchSource, value: usize);
        }
        unsafe { dispatch_source_merge_data(self, value) }
    }

    /// Sets a start time, interval, and leeway value for a timer source.
    ///
    ///
    /// Once this function returns, any pending source data accumulated for the
    /// previous timer values has been cleared; the next fire of the timer will
    /// occur at 'start', and every 'interval' nanoseconds thereafter until the
    /// timer source is canceled.
    ///
    /// Any fire of the timer may be delayed by the system in order to improve power
    /// consumption and system performance. The upper limit to the allowable delay
    /// may be configured with the 'leeway' argument, the lower limit is under the
    /// control of the system.
    ///
    /// For the initial timer fire at 'start', the upper limit to the allowable
    /// delay is set to 'leeway' nanoseconds. For the subsequent timer fires at
    /// 'start' + N * 'interval', the upper limit is MIN('leeway','interval'/2).
    ///
    /// The lower limit to the allowable delay may vary with process state such as
    /// visibility of application UI. If the specified timer source was created with
    /// a mask of DISPATCH_TIMER_STRICT, the system will make a best effort to
    /// strictly observe the provided 'leeway' value even if it is smaller than the
    /// current lower limit. Note that a minimal amount of delay is to be expected
    /// even if this flag is specified.
    ///
    /// The 'start' argument also determines which clock will be used for the timer:
    /// If 'start' is DISPATCH_TIME_NOW or was created with dispatch_time(3), the
    /// timer is based on up time (which is obtained from mach_absolute_time() on
    /// Apple platforms). If 'start' was created with dispatch_walltime(3), the
    /// timer is based on gettimeofday(3).
    ///
    /// Calling this function has no effect if the timer source has already been
    /// canceled.
    ///
    ///
    /// Parameter `start`: The start time of the timer. See dispatch_time() and dispatch_walltime()
    /// for more information.
    ///
    ///
    /// Parameter `interval`: The nanosecond interval for the timer. Use DISPATCH_TIME_FOREVER for a
    /// one-shot timer.
    ///
    ///
    /// Parameter `leeway`: The nanosecond leeway for the timer.
    #[doc(alias = "dispatch_source_set_timer")]
    #[inline]
    pub fn set_timer(self: &DispatchSource, start: DispatchTime, interval: u64, leeway: u64) {
        extern "C" {
            fn dispatch_source_set_timer(
                source: &DispatchSource,
                start: DispatchTime,
                interval: u64,
                leeway: u64,
            );
        }
        unsafe { dispatch_source_set_timer(self, start, interval, leeway) }
    }

    #[doc(alias = "dispatch_source_set_registration_handler")]
    #[cfg(feature = "block2")]
    #[inline]
    pub unsafe fn set_registration_handler_with_block(
        self: &DispatchSource,
        handler: dispatch_block_t,
    ) {
        extern "C" {
            fn dispatch_source_set_registration_handler(
                source: &DispatchSource,
                handler: dispatch_block_t,
            );
        }
        unsafe { dispatch_source_set_registration_handler(self, handler) }
    }

    /// Sets the registration handler function for the given dispatch source.
    ///
    ///
    /// See dispatch_source_set_registration_handler() for more details.
    ///
    ///
    /// Parameter `source`: The dispatch source to modify.
    /// The result of passing NULL in this parameter is undefined.
    ///
    ///
    /// Parameter `handler`: The registration handler function to submit to the source's target queue.
    /// The context parameter passed to the registration handler function is the
    /// current context of the dispatch source at the time the handler call is made.
    #[doc(alias = "dispatch_source_set_registration_handler_f")]
    #[inline]
    pub fn set_registration_handler_f(self: &DispatchSource, handler: dispatch_function_t) {
        extern "C" {
            fn dispatch_source_set_registration_handler_f(
                source: &DispatchSource,
                handler: dispatch_function_t,
            );
        }
        unsafe { dispatch_source_set_registration_handler_f(self, handler) }
    }
}

impl DispatchGroup {
    /// Creates new group with which blocks may be associated.
    ///
    ///
    /// This function creates a new group with which blocks may be associated.
    /// The dispatch group may be used to wait for the completion of the blocks it
    /// references. The group object memory is freed with dispatch_release().
    ///
    ///
    /// Returns: The newly created group, or NULL on failure.
    #[doc(alias = "dispatch_group_create")]
    #[must_use]
    #[inline]
    pub fn new() -> DispatchRetained<DispatchGroup> {
        extern "C" {
            fn dispatch_group_create() -> Option<NonNull<DispatchGroup>>;
        }
        let ret = unsafe { dispatch_group_create() };
        let ret =
            ret.expect("function was marked as returning non-null, but actually returned NULL");
        unsafe { DispatchRetained::from_raw(ret) }
    }

    #[doc(alias = "dispatch_group_async")]
    #[cfg(feature = "block2")]
    #[inline]
    pub unsafe fn exec_async_with_block(
        self: &DispatchGroup,
        queue: &DispatchQueue,
        block: dispatch_block_t,
    ) {
        extern "C" {
            fn dispatch_group_async(
                group: &DispatchGroup,
                queue: &DispatchQueue,
                block: dispatch_block_t,
            );
        }
        unsafe { dispatch_group_async(self, queue, block) }
    }

    /// Submits a function to a dispatch queue and associates the block with the
    /// given dispatch group.
    ///
    ///
    /// See dispatch_group_async() for details.
    ///
    ///
    /// Parameter `group`: A dispatch group to associate with the submitted function.
    /// The result of passing NULL in this parameter is undefined.
    ///
    ///
    /// Parameter `queue`: The dispatch queue to which the function will be submitted for asynchronous
    /// invocation.
    ///
    ///
    /// Parameter `context`: The application-defined context parameter to pass to the function.
    ///
    ///
    /// Parameter `work`: The application-defined function to invoke on the target queue. The first
    /// parameter passed to this function is the context provided to
    /// dispatch_group_async_f().
    #[doc(alias = "dispatch_group_async_f")]
    #[inline]
    pub unsafe fn exec_async_f(
        self: &DispatchGroup,
        queue: &DispatchQueue,
        context: *mut c_void,
        work: dispatch_function_t,
    ) {
        extern "C" {
            fn dispatch_group_async_f(
                group: &DispatchGroup,
                queue: &DispatchQueue,
                context: *mut c_void,
                work: dispatch_function_t,
            );
        }
        unsafe { dispatch_group_async_f(self, queue, context, work) }
    }
}

/// Wait synchronously until all the blocks associated with a group have
/// completed or until the specified timeout has elapsed.
///
///
/// This function waits for the completion of the blocks associated with the
/// given dispatch group, and returns after all blocks have completed or when
/// the specified timeout has elapsed.
///
/// This function will return immediately if there are no blocks associated
/// with the dispatch group (i.e. the group is empty).
///
/// The result of calling this function from multiple threads simultaneously
/// with the same dispatch group is undefined.
///
/// After the successful return of this function, the dispatch group is empty.
/// It may either be released with dispatch_release() or re-used for additional
/// blocks. See dispatch_group_async() for more information.
///
///
/// Parameter `group`: The dispatch group to wait on.
/// The result of passing NULL in this parameter is undefined.
///
///
/// Parameter `timeout`: When to timeout (see dispatch_time). As a convenience, there are the
/// DISPATCH_TIME_NOW and DISPATCH_TIME_FOREVER constants.
///
///
/// Returns: Returns zero on success (all blocks associated with the group completed
/// within the specified timeout) or non-zero on error (i.e. timed out).
#[inline]
pub extern "C" fn dispatch_group_wait(group: &DispatchGroup, timeout: DispatchTime) -> isize {
    extern "C" {
        fn dispatch_group_wait(group: &DispatchGroup, timeout: DispatchTime) -> isize;
    }
    unsafe { dispatch_group_wait(group, timeout) }
}

impl DispatchGroup {
    #[doc(alias = "dispatch_group_notify")]
    #[cfg(feature = "block2")]
    #[inline]
    pub unsafe fn notify_with_block(
        self: &DispatchGroup,
        queue: &DispatchQueue,
        block: dispatch_block_t,
    ) {
        extern "C" {
            fn dispatch_group_notify(
                group: &DispatchGroup,
                queue: &DispatchQueue,
                block: dispatch_block_t,
            );
        }
        unsafe { dispatch_group_notify(self, queue, block) }
    }

    /// Schedule a function to be submitted to a queue when all the blocks
    /// associated with a group have completed.
    ///
    ///
    /// See dispatch_group_notify() for details.
    ///
    ///
    /// Parameter `group`: The dispatch group to observe.
    /// The result of passing NULL in this parameter is undefined.
    ///
    ///
    /// Parameter `context`: The application-defined context parameter to pass to the function.
    ///
    ///
    /// Parameter `work`: The application-defined function to invoke on the target queue. The first
    /// parameter passed to this function is the context provided to
    /// dispatch_group_notify_f().
    #[doc(alias = "dispatch_group_notify_f")]
    #[inline]
    pub unsafe fn notify_f(
        self: &DispatchGroup,
        queue: &DispatchQueue,
        context: *mut c_void,
        work: dispatch_function_t,
    ) {
        extern "C" {
            fn dispatch_group_notify_f(
                group: &DispatchGroup,
                queue: &DispatchQueue,
                context: *mut c_void,
                work: dispatch_function_t,
            );
        }
        unsafe { dispatch_group_notify_f(self, queue, context, work) }
    }
}

extern "C" {
    /// Manually indicate a block has entered the group
    ///
    ///
    /// Calling this function indicates another block has joined the group through
    /// a means other than dispatch_group_async(). Calls to this function must be
    /// balanced with dispatch_group_leave().
    ///
    ///
    /// Parameter `group`: The dispatch group to update.
    /// The result of passing NULL in this parameter is undefined.
    pub fn dispatch_group_enter(group: &DispatchGroup);
}

impl DispatchGroup {
    /// Manually indicate a block in the group has completed
    ///
    ///
    /// Calling this function indicates block has completed and left the dispatch
    /// group by a means other than dispatch_group_async().
    ///
    ///
    /// Parameter `group`: The dispatch group to update.
    /// The result of passing NULL in this parameter is undefined.
    #[doc(alias = "dispatch_group_leave")]
    #[inline]
    pub unsafe fn leave(self: &DispatchGroup) {
        extern "C" {
            fn dispatch_group_leave(group: &DispatchGroup);
        }
        unsafe { dispatch_group_leave(self) }
    }
}

impl DispatchSemaphore {
    /// Creates new counting semaphore with an initial value.
    ///
    ///
    /// 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.
    ///
    ///
    /// Parameter `value`: The starting value for the semaphore. Passing a value less than zero will
    /// cause NULL to be returned.
    ///
    ///
    /// Returns: The newly created semaphore, or NULL on failure.
    #[doc(alias = "dispatch_semaphore_create")]
    #[must_use]
    #[inline]
    pub fn new(value: isize) -> DispatchRetained<DispatchSemaphore> {
        extern "C" {
            fn dispatch_semaphore_create(value: isize) -> Option<NonNull<DispatchSemaphore>>;
        }
        let ret = unsafe { dispatch_semaphore_create(value) };
        let ret =
            ret.expect("function was marked as returning non-null, but actually returned NULL");
        unsafe { DispatchRetained::from_raw(ret) }
    }

    /// Wait (decrement) for a semaphore.
    ///
    ///
    /// Decrement the counting semaphore. If the resulting value is less than zero,
    /// this function waits for a signal to occur before returning. If the timeout is
    /// reached without a signal being received, the semaphore is re-incremented
    /// before the function returns.
    ///
    ///
    /// Parameter `dsema`: The semaphore. The result of passing NULL in this parameter is undefined.
    ///
    ///
    /// Parameter `timeout`: When to timeout (see dispatch_time). As a convenience, there are the
    /// DISPATCH_TIME_NOW and DISPATCH_TIME_FOREVER constants.
    ///
    ///
    /// Returns: Returns zero on success, or non-zero if the timeout occurred.
    #[doc(alias = "dispatch_semaphore_wait")]
    #[inline]
    pub fn wait(self: &DispatchSemaphore, timeout: DispatchTime) -> isize {
        extern "C" {
            fn dispatch_semaphore_wait(dsema: &DispatchSemaphore, timeout: DispatchTime) -> isize;
        }
        unsafe { dispatch_semaphore_wait(self, timeout) }
    }

    /// Signal (increment) a semaphore.
    ///
    ///
    /// Increment the counting semaphore. If the previous value was less than zero,
    /// this function wakes a waiting thread before returning.
    ///
    ///
    /// Parameter `dsema`: The counting semaphore.
    /// The result of passing NULL in this parameter is undefined.
    ///
    ///
    /// Returns: This function returns non-zero if a thread is woken. Otherwise, zero is
    /// returned.
    #[doc(alias = "dispatch_semaphore_signal")]
    #[inline]
    pub fn signal(self: &DispatchSemaphore) -> isize {
        extern "C" {
            fn dispatch_semaphore_signal(dsema: &DispatchSemaphore) -> isize;
        }
        unsafe { dispatch_semaphore_signal(self) }
    }
}

/// A predicate for use with dispatch_once(). It must be initialized to zero.
/// Note: static and global variables default to zero.
///
/// See also [Apple's documentation](https://developer.apple.com/documentation/dispatch/dispatch_once_t?language=objc)
pub type dispatch_once_t = isize;

impl DispatchOnce {
    #[doc(alias = "dispatch_once")]
    #[cfg(feature = "block2")]
    #[inline]
    pub unsafe fn once_with_block(predicate: NonNull<dispatch_once_t>, block: dispatch_block_t) {
        extern "C" {
            fn dispatch_once(predicate: NonNull<dispatch_once_t>, block: dispatch_block_t);
        }
        unsafe { dispatch_once(predicate, block) }
    }

    #[doc(alias = "dispatch_once_f")]
    #[inline]
    pub unsafe fn once_f(
        predicate: NonNull<dispatch_once_t>,
        context: *mut c_void,
        function: dispatch_function_t,
    ) {
        extern "C" {
            fn dispatch_once_f(
                predicate: NonNull<dispatch_once_t>,
                context: *mut c_void,
                function: dispatch_function_t,
            );
        }
        unsafe { dispatch_once_f(predicate, context, function) }
    }
}

extern "C" {
    /// [Apple's documentation](https://developer.apple.com/documentation/dispatch/_dispatch_data_empty?language=objc)
    pub static _dispatch_data_empty: DispatchData;
}

extern "C" {
    /// [Apple's documentation](https://developer.apple.com/documentation/dispatch/_dispatch_data_destructor_free?language=objc)
    #[cfg(feature = "block2")]
    pub static _dispatch_data_destructor_free: dispatch_block_t;
}

extern "C" {
    /// [Apple's documentation](https://developer.apple.com/documentation/dispatch/_dispatch_data_destructor_munmap?language=objc)
    #[cfg(feature = "block2")]
    pub static _dispatch_data_destructor_munmap: dispatch_block_t;
}

impl DispatchData {
    /// Creates a dispatch data object from the given contiguous buffer of memory. If
    /// a non-default destructor is provided, ownership of the buffer remains with
    /// the caller (i.e. the bytes will not be copied). The last release of the data
    /// object will result in the invocation of the specified destructor on the
    /// specified queue to free the buffer.
    ///
    /// If the DISPATCH_DATA_DESTRUCTOR_FREE destructor is provided the buffer will
    /// be freed via free(3) and the queue argument ignored.
    ///
    /// If the DISPATCH_DATA_DESTRUCTOR_DEFAULT destructor is provided, data object
    /// creation will copy the buffer into internal memory managed by the system.
    ///
    ///
    /// Parameter `buffer`: A contiguous buffer of data.
    ///
    /// Parameter `size`: The size of the contiguous buffer of data.
    ///
    /// Parameter `queue`: The queue to which the destructor should be submitted.
    ///
    /// Parameter `destructor`: The destructor responsible for freeing the data when it
    /// is no longer needed.
    ///
    /// Returns: A newly created dispatch data object.
    #[doc(alias = "dispatch_data_create")]
    #[cfg(feature = "block2")]
    #[must_use]
    #[inline]
    pub unsafe fn new(
        buffer: NonNull<c_void>,
        size: usize,
        queue: Option<&DispatchQueue>,
        destructor: dispatch_block_t,
    ) -> DispatchRetained<DispatchData> {
        extern "C" {
            fn dispatch_data_create(
                buffer: NonNull<c_void>,
                size: usize,
                queue: Option<&DispatchQueue>,
                destructor: dispatch_block_t,
            ) -> Option<NonNull<DispatchData>>;
        }
        let ret = unsafe { dispatch_data_create(buffer, size, queue, destructor) };
        let ret =
            ret.expect("function was marked as returning non-null, but actually returned NULL");
        unsafe { DispatchRetained::from_raw(ret) }
    }

    /// Returns the logical size of the memory region(s) represented by the specified
    /// dispatch data object.
    ///
    ///
    /// Parameter `data`: The dispatch data object to query.
    ///
    /// Returns: The number of bytes represented by the data object.
    #[doc(alias = "dispatch_data_get_size")]
    #[inline]
    pub fn size(self: &DispatchData) -> usize {
        extern "C" {
            fn dispatch_data_get_size(data: &DispatchData) -> usize;
        }
        unsafe { dispatch_data_get_size(self) }
    }

    /// Maps the memory represented by the specified dispatch data object as a single
    /// contiguous memory region and returns a new data object representing it.
    /// If non-NULL references to a pointer and a size variable are provided, they
    /// are filled with the location and extent of that region. These allow direct
    /// read access to the represented memory, but are only valid until the returned
    /// object is released. Under ARC, if that object is held in a variable with
    /// automatic storage, care needs to be taken to ensure that it is not released
    /// by the compiler before memory access via the pointer has been completed.
    ///
    ///
    /// Parameter `data`: The dispatch data object to map.
    ///
    /// Parameter `buffer_ptr`: A pointer to a pointer variable to be filled with the
    /// location of the mapped contiguous memory region, or
    /// NULL.
    ///
    /// Parameter `size_ptr`: A pointer to a size_t variable to be filled with the
    /// size of the mapped contiguous memory region, or NULL.
    ///
    /// Returns: A newly created dispatch data object.
    #[doc(alias = "dispatch_data_create_map")]
    #[must_use]
    #[inline]
    pub unsafe fn map(
        self: &DispatchData,
        buffer_ptr: *mut *const c_void,
        size_ptr: *mut usize,
    ) -> DispatchRetained<DispatchData> {
        extern "C" {
            fn dispatch_data_create_map(
                data: &DispatchData,
                buffer_ptr: *mut *const c_void,
                size_ptr: *mut usize,
            ) -> Option<NonNull<DispatchData>>;
        }
        let ret = unsafe { dispatch_data_create_map(self, buffer_ptr, size_ptr) };
        let ret =
            ret.expect("function was marked as returning non-null, but actually returned NULL");
        unsafe { DispatchRetained::from_raw(ret) }
    }

    /// Returns a new dispatch data object representing the concatenation of the
    /// specified data objects. Those objects may be released by the application
    /// after the call returns (however, the system might not deallocate the memory
    /// region(s) described by them until the newly created object has also been
    /// released).
    ///
    ///
    /// Parameter `data1`: The data object representing the region(s) of memory to place
    /// at the beginning of the newly created object.
    ///
    /// Parameter `data2`: The data object representing the region(s) of memory to place
    /// at the end of the newly created object.
    ///
    /// Returns: A newly created object representing the concatenation of the
    /// data1 and data2 objects.
    #[doc(alias = "dispatch_data_create_concat")]
    #[must_use]
    #[inline]
    pub fn concat(self: &DispatchData, data2: &DispatchData) -> DispatchRetained<DispatchData> {
        extern "C" {
            fn dispatch_data_create_concat(
                data1: &DispatchData,
                data2: &DispatchData,
            ) -> Option<NonNull<DispatchData>>;
        }
        let ret = unsafe { dispatch_data_create_concat(self, data2) };
        let ret =
            ret.expect("function was marked as returning non-null, but actually returned NULL");
        unsafe { DispatchRetained::from_raw(ret) }
    }

    /// Returns a new dispatch data object representing a subrange of the specified
    /// data object, which may be released by the application after the call returns
    /// (however, the system might not deallocate the memory region(s) described by
    /// that object until the newly created object has also been released).
    ///
    ///
    /// Parameter `data`: The data object representing the region(s) of memory to
    /// create a subrange of.
    ///
    /// Parameter `offset`: The offset into the data object where the subrange
    /// starts.
    ///
    /// Parameter `length`: The length of the range.
    ///
    /// Returns: A newly created object representing the specified
    /// subrange of the data object.
    #[doc(alias = "dispatch_data_create_subrange")]
    #[must_use]
    #[inline]
    pub unsafe fn subrange(
        self: &DispatchData,
        offset: usize,
        length: usize,
    ) -> DispatchRetained<DispatchData> {
        extern "C" {
            fn dispatch_data_create_subrange(
                data: &DispatchData,
                offset: usize,
                length: usize,
            ) -> Option<NonNull<DispatchData>>;
        }
        let ret = unsafe { dispatch_data_create_subrange(self, offset, length) };
        let ret =
            ret.expect("function was marked as returning non-null, but actually returned NULL");
        unsafe { DispatchRetained::from_raw(ret) }
    }
}

/// A block to be invoked for every contiguous memory region in a data object.
///
///
/// Parameter `region`: A data object representing the current region.
///
/// Parameter `offset`: The logical offset of the current region to the start
/// of the data object.
///
/// Parameter `buffer`: The location of the memory for the current region.
///
/// Parameter `size`: The size of the memory for the current region.
///
/// Returns: A Boolean indicating whether traversal should continue.
///
/// See also [Apple's documentation](https://developer.apple.com/documentation/dispatch/dispatch_data_applier_t?language=objc)
#[cfg(feature = "block2")]
pub type dispatch_data_applier_t =
    *mut block2::DynBlock<dyn Fn(NonNull<DispatchData>, usize, NonNull<c_void>, usize) -> bool>;

impl DispatchData {
    /// Traverse the memory regions represented by the specified dispatch data object
    /// in logical order and invoke the specified block once for every contiguous
    /// memory region encountered.
    ///
    /// Each invocation of the block is passed a data object representing the current
    /// region and its logical offset, along with the memory location and extent of
    /// the region. These allow direct read access to the memory region, but are only
    /// valid until the passed-in region object is released. Note that the region
    /// object is released by the system when the block returns, it is the
    /// responsibility of the application to retain it if the region object or the
    /// associated memory location are needed after the block returns.
    ///
    ///
    /// Parameter `data`: The data object to traverse.
    ///
    /// Parameter `applier`: The block to be invoked for every contiguous memory
    /// region in the data object.
    ///
    /// Returns: A Boolean indicating whether traversal completed
    /// successfully.
    #[doc(alias = "dispatch_data_apply")]
    #[cfg(feature = "block2")]
    #[inline]
    pub unsafe fn apply(self: &DispatchData, applier: dispatch_data_applier_t) -> bool {
        extern "C" {
            fn dispatch_data_apply(data: &DispatchData, applier: dispatch_data_applier_t) -> bool;
        }
        unsafe { dispatch_data_apply(self, applier) }
    }

    /// Finds the contiguous memory region containing the specified location among
    /// the regions represented by the specified object and returns a copy of the
    /// internal dispatch data object representing that region along with its logical
    /// offset in the specified object.
    ///
    ///
    /// Parameter `data`: The dispatch data object to query.
    ///
    /// Parameter `location`: The logical position in the data object to query.
    ///
    /// Parameter `offset_ptr`: A pointer to a size_t variable to be filled with the
    /// logical offset of the returned region object to the
    /// start of the queried data object.
    ///
    /// Returns: A newly created dispatch data object.
    #[doc(alias = "dispatch_data_copy_region")]
    #[must_use]
    #[inline]
    pub unsafe fn region(
        self: &DispatchData,
        location: usize,
        offset_ptr: NonNull<usize>,
    ) -> DispatchRetained<DispatchData> {
        extern "C" {
            fn dispatch_data_copy_region(
                data: &DispatchData,
                location: usize,
                offset_ptr: NonNull<usize>,
            ) -> Option<NonNull<DispatchData>>;
        }
        let ret = unsafe { dispatch_data_copy_region(self, location, offset_ptr) };
        let ret =
            ret.expect("function was marked as returning non-null, but actually returned NULL");
        unsafe { DispatchRetained::from_raw(ret) }
    }
}

/// [Apple's documentation](https://developer.apple.com/documentation/dispatch/dispatch_fd_t?language=objc)
pub type dispatch_fd_t = c_int;

extern "C" {
    /// Schedule a read operation for asynchronous execution on the specified file
    /// descriptor. The specified handler is enqueued with the data read from the
    /// file descriptor when the operation has completed or an error occurs.
    ///
    /// The data object passed to the handler will be automatically released by the
    /// system when the handler returns. It is the responsibility of the application
    /// to retain, concatenate or copy the data object if it is needed after the
    /// handler returns.
    ///
    /// The data object passed to the handler will only contain as much data as is
    /// currently available from the file descriptor (up to the specified length).
    ///
    /// If an unrecoverable error occurs on the file descriptor, the handler will be
    /// enqueued with the appropriate error code along with a data object of any data
    /// that could be read successfully.
    ///
    /// An invocation of the handler with an error code of zero and an empty data
    /// object indicates that EOF was reached.
    ///
    /// The system takes control of the file descriptor until the handler is
    /// enqueued, and during this time file descriptor flags such as O_NONBLOCK will
    /// be modified by the system on behalf of the application. It is an error for
    /// the application to modify a file descriptor directly while it is under the
    /// control of the system, but it may create additional dispatch I/O convenience
    /// operations or dispatch I/O channels associated with that file descriptor.
    ///
    ///
    /// Parameter `fd`: The file descriptor from which to read the data.
    ///
    /// Parameter `length`: The length of data to read from the file descriptor,
    /// or SIZE_MAX to indicate that all of the data currently
    /// available from the file descriptor should be read.
    ///
    /// Parameter `queue`: The dispatch queue to which the handler should be
    /// submitted.
    ///
    /// Parameter `handler`: The handler to enqueue when data is ready to be
    /// delivered.
    /// param data    The data read from the file descriptor.
    /// param error    An errno condition for the read operation or
    /// zero if the read was successful.
    #[cfg(feature = "block2")]
    pub fn dispatch_read(
        fd: dispatch_fd_t,
        length: usize,
        queue: &DispatchQueue,
        handler: &block2::DynBlock<dyn Fn(NonNull<DispatchData>, c_int)>,
    );
}

extern "C" {
    /// Schedule a write operation for asynchronous execution on the specified file
    /// descriptor. The specified handler is enqueued when the operation has
    /// completed or an error occurs.
    ///
    /// If an unrecoverable error occurs on the file descriptor, the handler will be
    /// enqueued with the appropriate error code along with the data that could not
    /// be successfully written.
    ///
    /// An invocation of the handler with an error code of zero indicates that the
    /// data was fully written to the channel.
    ///
    /// The system takes control of the file descriptor until the handler is
    /// enqueued, and during this time file descriptor flags such as O_NONBLOCK will
    /// be modified by the system on behalf of the application. It is an error for
    /// the application to modify a file descriptor directly while it is under the
    /// control of the system, but it may create additional dispatch I/O convenience
    /// operations or dispatch I/O channels associated with that file descriptor.
    ///
    ///
    /// Parameter `fd`: The file descriptor to which to write the data.
    ///
    /// Parameter `data`: The data object to write to the file descriptor.
    ///
    /// Parameter `queue`: The dispatch queue to which the handler should be
    /// submitted.
    ///
    /// Parameter `handler`: The handler to enqueue when the data has been written.
    /// param data    The data that could not be written to the I/O
    /// channel, or NULL.
    /// param error    An errno condition for the write operation or
    /// zero if the write was successful.
    #[cfg(feature = "block2")]
    pub fn dispatch_write(
        fd: dispatch_fd_t,
        data: &DispatchData,
        queue: &DispatchQueue,
        handler: &block2::DynBlock<dyn Fn(*mut DispatchData, c_int)>,
    );
}

impl DispatchIO {
    /// Create a dispatch I/O channel associated with a file descriptor. The system
    /// takes control of the file descriptor until the channel is closed, an error
    /// occurs on the file descriptor or all references to the channel are released.
    /// At that time the specified cleanup handler will be enqueued and control over
    /// the file descriptor relinquished.
    ///
    /// While a file descriptor is under the control of a dispatch I/O channel, file
    /// descriptor flags such as O_NONBLOCK will be modified by the system on behalf
    /// of the application. It is an error for the application to modify a file
    /// descriptor directly while it is under the control of a dispatch I/O channel,
    /// but it may create additional channels associated with that file descriptor.
    ///
    ///
    /// Parameter `type`: The desired type of I/O channel (DISPATCH_IO_STREAM
    /// or DISPATCH_IO_RANDOM).
    ///
    /// Parameter `fd`: The file descriptor to associate with the I/O channel.
    ///
    /// Parameter `queue`: The dispatch queue to which the handler should be submitted.
    ///
    /// Parameter `cleanup_handler`: The handler to enqueue when the system
    /// relinquishes control over the file descriptor.
    /// param error        An errno condition if control is relinquished
    /// because channel creation failed, zero otherwise.
    ///
    /// Returns: The newly created dispatch I/O channel or NULL if an error
    /// occurred (invalid type specified).
    #[doc(alias = "dispatch_io_create")]
    #[cfg(feature = "block2")]
    #[must_use]
    #[inline]
    pub unsafe fn new(
        r#type: DispatchIOStreamType,
        fd: dispatch_fd_t,
        queue: &DispatchQueue,
        cleanup_handler: &block2::DynBlock<dyn Fn(c_int)>,
    ) -> DispatchRetained<DispatchIO> {
        extern "C" {
            fn dispatch_io_create(
                r#type: DispatchIOStreamType,
                fd: dispatch_fd_t,
                queue: &DispatchQueue,
                cleanup_handler: &block2::DynBlock<dyn Fn(c_int)>,
            ) -> Option<NonNull<DispatchIO>>;
        }
        let ret = unsafe { dispatch_io_create(r#type, fd, queue, cleanup_handler) };
        let ret =
            ret.expect("function was marked as returning non-null, but actually returned NULL");
        unsafe { DispatchRetained::from_raw(ret) }
    }

    /// Create a dispatch I/O channel associated with a path name. The specified
    /// path, oflag and mode parameters will be passed to open(2) when the first I/O
    /// operation on the channel is ready to execute and the resulting file
    /// descriptor will remain open and under the control of the system until the
    /// channel is closed, an error occurs on the file descriptor or all references
    /// to the channel are released. At that time the file descriptor will be closed
    /// and the specified cleanup handler will be enqueued.
    ///
    ///
    /// Parameter `type`: The desired type of I/O channel (DISPATCH_IO_STREAM
    /// or DISPATCH_IO_RANDOM).
    ///
    /// Parameter `path`: The absolute path to associate with the I/O channel.
    ///
    /// Parameter `oflag`: The flags to pass to open(2) when opening the file at
    /// path.
    ///
    /// Parameter `mode`: The mode to pass to open(2) when creating the file at
    /// path (i.e. with flag O_CREAT), zero otherwise.
    ///
    /// Parameter `queue`: The dispatch queue to which the handler should be
    /// submitted.
    ///
    /// Parameter `cleanup_handler`: The handler to enqueue when the system
    /// has closed the file at path.
    /// param error        An errno condition if control is relinquished
    /// because channel creation or opening of the
    /// specified file failed, zero otherwise.
    ///
    /// Returns: The newly created dispatch I/O channel or NULL if an error
    /// occurred (invalid type or non-absolute path specified).
    #[doc(alias = "dispatch_io_create_with_path")]
    #[cfg(all(feature = "block2", feature = "libc"))]
    #[must_use]
    #[inline]
    pub unsafe fn with_path(
        r#type: DispatchIOStreamType,
        path: NonNull<c_char>,
        oflag: c_int,
        mode: libc::mode_t,
        queue: &DispatchQueue,
        cleanup_handler: &block2::DynBlock<dyn Fn(c_int)>,
    ) -> DispatchRetained<DispatchIO> {
        extern "C" {
            fn dispatch_io_create_with_path(
                r#type: DispatchIOStreamType,
                path: NonNull<c_char>,
                oflag: c_int,
                mode: libc::mode_t,
                queue: &DispatchQueue,
                cleanup_handler: &block2::DynBlock<dyn Fn(c_int)>,
            ) -> Option<NonNull<DispatchIO>>;
        }
        let ret = unsafe {
            dispatch_io_create_with_path(r#type, path, oflag, mode, queue, cleanup_handler)
        };
        let ret =
            ret.expect("function was marked as returning non-null, but actually returned NULL");
        unsafe { DispatchRetained::from_raw(ret) }
    }

    /// Create a new dispatch I/O channel from an existing dispatch I/O channel.
    /// The new channel inherits the file descriptor or path name associated with
    /// the existing channel, but not its channel type or policies.
    ///
    /// If the existing channel is associated with a file descriptor, control by the
    /// system over that file descriptor is extended until the new channel is also
    /// closed, an error occurs on the file descriptor, or all references to both
    /// channels are released. At that time the specified cleanup handler will be
    /// enqueued and control over the file descriptor relinquished.
    ///
    /// While a file descriptor is under the control of a dispatch I/O channel, file
    /// descriptor flags such as O_NONBLOCK will be modified by the system on behalf
    /// of the application. It is an error for the application to modify a file
    /// descriptor directly while it is under the control of a dispatch I/O channel,
    /// but it may create additional channels associated with that file descriptor.
    ///
    ///
    /// Parameter `type`: The desired type of I/O channel (DISPATCH_IO_STREAM
    /// or DISPATCH_IO_RANDOM).
    ///
    /// Parameter `io`: The existing channel to create the new I/O channel from.
    ///
    /// Parameter `queue`: The dispatch queue to which the handler should be submitted.
    ///
    /// Parameter `cleanup_handler`: The handler to enqueue when the system
    /// relinquishes control over the file descriptor
    /// (resp. closes the file at path) associated with
    /// the existing channel.
    /// param error        An errno condition if control is relinquished
    /// because channel creation failed, zero otherwise.
    ///
    /// Returns: The newly created dispatch I/O channel or NULL if an error
    /// occurred (invalid type specified).
    #[doc(alias = "dispatch_io_create_with_io")]
    #[cfg(feature = "block2")]
    #[must_use]
    #[inline]
    pub fn with_io(
        r#type: DispatchIOStreamType,
        io: &DispatchIO,
        queue: &DispatchQueue,
        cleanup_handler: &block2::DynBlock<dyn Fn(c_int)>,
    ) -> DispatchRetained<DispatchIO> {
        extern "C" {
            fn dispatch_io_create_with_io(
                r#type: DispatchIOStreamType,
                io: &DispatchIO,
                queue: &DispatchQueue,
                cleanup_handler: &block2::DynBlock<dyn Fn(c_int)>,
            ) -> Option<NonNull<DispatchIO>>;
        }
        let ret = unsafe { dispatch_io_create_with_io(r#type, io, queue, cleanup_handler) };
        let ret =
            ret.expect("function was marked as returning non-null, but actually returned NULL");
        unsafe { DispatchRetained::from_raw(ret) }
    }
}

/// The prototype of I/O handler blocks for dispatch I/O operations.
///
///
/// Parameter `done`: A flag indicating whether the operation is complete.
///
/// Parameter `data`: The data object to be handled.
///
/// Parameter `error`: An errno condition for the operation.
///
/// See also [Apple's documentation](https://developer.apple.com/documentation/dispatch/dispatch_io_handler_t?language=objc)
#[cfg(feature = "block2")]
pub type dispatch_io_handler_t = *mut block2::DynBlock<dyn Fn(bool, *mut DispatchData, c_int)>;

impl DispatchIO {
    /// Schedule a read operation for asynchronous execution on the specified I/O
    /// channel. The I/O handler is enqueued one or more times depending on the
    /// general load of the system and the policy specified on the I/O channel.
    ///
    /// Any data read from the channel is described by the dispatch data object
    /// passed to the I/O handler. This object will be automatically released by the
    /// system when the I/O handler returns. It is the responsibility of the
    /// application to retain, concatenate or copy the data object if it is needed
    /// after the I/O handler returns.
    ///
    /// Dispatch I/O handlers are not reentrant. The system will ensure that no new
    /// I/O handler instance is invoked until the previously enqueued handler block
    /// has returned.
    ///
    /// An invocation of the I/O handler with the done flag set indicates that the
    /// read operation is complete and that the handler will not be enqueued again.
    ///
    /// If an unrecoverable error occurs on the I/O channel's underlying file
    /// descriptor, the I/O handler will be enqueued with the done flag set, the
    /// appropriate error code and a NULL data object.
    ///
    /// An invocation of the I/O handler with the done flag set, an error code of
    /// zero and an empty data object indicates that EOF was reached.
    ///
    ///
    /// Parameter `channel`: The dispatch I/O channel from which to read the data.
    ///
    /// Parameter `offset`: The offset relative to the channel position from which
    /// to start reading (only for DISPATCH_IO_RANDOM).
    ///
    /// Parameter `length`: The length of data to read from the I/O channel, or
    /// SIZE_MAX to indicate that data should be read until EOF
    /// is reached.
    ///
    /// Parameter `queue`: The dispatch queue to which the I/O handler should be
    /// submitted.
    ///
    /// Parameter `io_handler`: The I/O handler to enqueue when data is ready to be
    /// delivered.
    /// param done    A flag indicating whether the operation is complete.
    /// param data    An object with the data most recently read from the
    /// I/O channel as part of this read operation, or NULL.
    /// param error    An errno condition for the read operation or zero if
    /// the read was successful.
    #[doc(alias = "dispatch_io_read")]
    #[cfg(all(feature = "block2", feature = "libc"))]
    #[inline]
    pub unsafe fn read(
        self: &DispatchIO,
        offset: libc::off_t,
        length: usize,
        queue: &DispatchQueue,
        io_handler: dispatch_io_handler_t,
    ) {
        extern "C" {
            fn dispatch_io_read(
                channel: &DispatchIO,
                offset: libc::off_t,
                length: usize,
                queue: &DispatchQueue,
                io_handler: dispatch_io_handler_t,
            );
        }
        unsafe { dispatch_io_read(self, offset, length, queue, io_handler) }
    }

    /// Schedule a write operation for asynchronous execution on the specified I/O
    /// channel. The I/O handler is enqueued one or more times depending on the
    /// general load of the system and the policy specified on the I/O channel.
    ///
    /// Any data remaining to be written to the I/O channel is described by the
    /// dispatch data object passed to the I/O handler. This object will be
    /// automatically released by the system when the I/O handler returns. It is the
    /// responsibility of the application to retain, concatenate or copy the data
    /// object if it is needed after the I/O handler returns.
    ///
    /// Dispatch I/O handlers are not reentrant. The system will ensure that no new
    /// I/O handler instance is invoked until the previously enqueued handler block
    /// has returned.
    ///
    /// An invocation of the I/O handler with the done flag set indicates that the
    /// write operation is complete and that the handler will not be enqueued again.
    ///
    /// If an unrecoverable error occurs on the I/O channel's underlying file
    /// descriptor, the I/O handler will be enqueued with the done flag set, the
    /// appropriate error code and an object containing the data that could not be
    /// written.
    ///
    /// An invocation of the I/O handler with the done flag set and an error code of
    /// zero indicates that the data was fully written to the channel.
    ///
    ///
    /// Parameter `channel`: The dispatch I/O channel on which to write the data.
    ///
    /// Parameter `offset`: The offset relative to the channel position from which
    /// to start writing (only for DISPATCH_IO_RANDOM).
    ///
    /// Parameter `data`: The data to write to the I/O channel. The data object
    /// will be retained by the system until the write operation
    /// is complete.
    ///
    /// Parameter `queue`: The dispatch queue to which the I/O handler should be
    /// submitted.
    ///
    /// Parameter `io_handler`: The I/O handler to enqueue when data has been delivered.
    /// param done    A flag indicating whether the operation is complete.
    /// param data    An object of the data remaining to be
    /// written to the I/O channel as part of this write
    /// operation, or NULL.
    /// param error    An errno condition for the write operation or zero
    /// if the write was successful.
    #[doc(alias = "dispatch_io_write")]
    #[cfg(all(feature = "block2", feature = "libc"))]
    #[inline]
    pub unsafe fn write(
        self: &DispatchIO,
        offset: libc::off_t,
        data: &DispatchData,
        queue: &DispatchQueue,
        io_handler: dispatch_io_handler_t,
    ) {
        extern "C" {
            fn dispatch_io_write(
                channel: &DispatchIO,
                offset: libc::off_t,
                data: &DispatchData,
                queue: &DispatchQueue,
                io_handler: dispatch_io_handler_t,
            );
        }
        unsafe { dispatch_io_write(self, offset, data, queue, io_handler) }
    }

    /// Close the specified I/O channel to new read or write operations; scheduling
    /// operations on a closed channel results in their handler returning an error.
    ///
    /// If the DISPATCH_IO_STOP flag is provided, the system will make a best effort
    /// to interrupt any outstanding read and write operations on the I/O channel,
    /// otherwise those operations will run to completion normally.
    /// Partial results of read and write operations may be returned even after a
    /// channel is closed with the DISPATCH_IO_STOP flag.
    /// The final invocation of an I/O handler of an interrupted operation will be
    /// passed an ECANCELED error code, as will the I/O handler of an operation
    /// scheduled on a closed channel.
    ///
    ///
    /// Parameter `channel`: The dispatch I/O channel to close.
    ///
    /// Parameter `flags`: The flags for the close operation.
    #[doc(alias = "dispatch_io_close")]
    #[inline]
    pub fn close(self: &DispatchIO, flags: DispatchIOCloseFlags) {
        extern "C" {
            fn dispatch_io_close(channel: &DispatchIO, flags: DispatchIOCloseFlags);
        }
        unsafe { dispatch_io_close(self, flags) }
    }

    /// Schedule a barrier operation on the specified I/O channel; all previously
    /// scheduled operations on the channel will complete before the provided
    /// barrier block is enqueued onto the global queue determined by the channel's
    /// target queue, and no subsequently scheduled operations will start until the
    /// barrier block has returned.
    ///
    /// If multiple channels are associated with the same file descriptor, a barrier
    /// operation scheduled on any of these channels will act as a barrier across all
    /// channels in question, i.e. all previously scheduled operations on any of the
    /// channels will complete before the barrier block is enqueued, and no
    /// operations subsequently scheduled on any of the channels will start until the
    /// barrier block has returned.
    ///
    /// While the barrier block is running, it may safely operate on the channel's
    /// underlying file descriptor with fsync(2), lseek(2) etc. (but not close(2)).
    ///
    ///
    /// Parameter `channel`: The dispatch I/O channel to schedule the barrier on.
    ///
    /// Parameter `barrier`: The barrier block.
    #[doc(alias = "dispatch_io_barrier")]
    #[cfg(feature = "block2")]
    #[inline]
    pub unsafe fn barrier(self: &DispatchIO, barrier: dispatch_block_t) {
        extern "C" {
            fn dispatch_io_barrier(channel: &DispatchIO, barrier: dispatch_block_t);
        }
        unsafe { dispatch_io_barrier(self, barrier) }
    }

    /// Returns the file descriptor underlying a dispatch I/O channel.
    ///
    /// Will return -1 for a channel closed with dispatch_io_close() and for a
    /// channel associated with a path name that has not yet been open(2)ed.
    ///
    /// If called from a barrier block scheduled on a channel associated with a path
    /// name that has not yet been open(2)ed, this will trigger the channel open(2)
    /// operation and return the resulting file descriptor.
    ///
    ///
    /// Parameter `channel`: The dispatch I/O channel to query.
    ///
    /// Returns: The file descriptor underlying the channel, or -1.
    #[doc(alias = "dispatch_io_get_descriptor")]
    #[must_use]
    #[inline]
    pub fn descriptor(self: &DispatchIO) -> dispatch_fd_t {
        extern "C" {
            fn dispatch_io_get_descriptor(channel: &DispatchIO) -> dispatch_fd_t;
        }
        unsafe { dispatch_io_get_descriptor(self) }
    }

    /// Set a high water mark on the I/O channel for all operations.
    ///
    /// The system will make a best effort to enqueue I/O handlers with partial
    /// results as soon the number of bytes processed by an operation (i.e. read or
    /// written) reaches the high water mark.
    ///
    /// The size of data objects passed to I/O handlers for this channel will never
    /// exceed the specified high water mark.
    ///
    /// The default value for the high water mark is unlimited (i.e. SIZE_MAX).
    ///
    ///
    /// Parameter `channel`: The dispatch I/O channel on which to set the policy.
    ///
    /// Parameter `high_water`: The number of bytes to use as a high water mark.
    #[doc(alias = "dispatch_io_set_high_water")]
    #[inline]
    pub fn set_high_water(self: &DispatchIO, high_water: usize) {
        extern "C" {
            fn dispatch_io_set_high_water(channel: &DispatchIO, high_water: usize);
        }
        unsafe { dispatch_io_set_high_water(self, high_water) }
    }

    /// Set a low water mark on the I/O channel for all operations.
    ///
    /// The system will process (i.e. read or write) at least the low water mark
    /// number of bytes for an operation before enqueueing I/O handlers with partial
    /// results.
    ///
    /// The size of data objects passed to intermediate I/O handler invocations for
    /// this channel (i.e. excluding the final invocation) will never be smaller than
    /// the specified low water mark, except if the channel has an interval with the
    /// DISPATCH_IO_STRICT_INTERVAL flag set or if EOF or an error was encountered.
    ///
    /// I/O handlers should be prepared to receive amounts of data significantly
    /// larger than the low water mark in general. If an I/O handler requires
    /// intermediate results of fixed size, set both the low and and the high water
    /// mark to that size.
    ///
    /// The default value for the low water mark is unspecified, but must be assumed
    /// to be such that intermediate handler invocations may occur.
    /// If I/O handler invocations with partial results are not desired, set the
    /// low water mark to SIZE_MAX.
    ///
    ///
    /// Parameter `channel`: The dispatch I/O channel on which to set the policy.
    ///
    /// Parameter `low_water`: The number of bytes to use as a low water mark.
    #[doc(alias = "dispatch_io_set_low_water")]
    #[inline]
    pub fn set_low_water(self: &DispatchIO, low_water: usize) {
        extern "C" {
            fn dispatch_io_set_low_water(channel: &DispatchIO, low_water: usize);
        }
        unsafe { dispatch_io_set_low_water(self, low_water) }
    }

    /// Set a nanosecond interval at which I/O handlers are to be enqueued on the
    /// I/O channel for all operations.
    ///
    /// This allows an application to receive periodic feedback on the progress of
    /// read and write operations, e.g. for the purposes of displaying progress bars.
    ///
    /// If the amount of data ready to be delivered to an I/O handler at the interval
    /// is inferior to the channel low water mark, the handler will only be enqueued
    /// if the DISPATCH_IO_STRICT_INTERVAL flag is set.
    ///
    /// Note that the system may defer enqueueing interval I/O handlers by a small
    /// unspecified amount of leeway in order to align with other system activity for
    /// improved system performance or power consumption.
    ///
    ///
    /// Parameter `channel`: The dispatch I/O channel on which to set the policy.
    ///
    /// Parameter `interval`: The interval in nanoseconds at which delivery of the I/O
    /// handler is desired.
    ///
    /// Parameter `flags`: Flags indicating desired data delivery behavior at
    /// interval time.
    #[doc(alias = "dispatch_io_set_interval")]
    #[inline]
    pub fn set_interval(self: &DispatchIO, interval: u64, flags: DispatchIOIntervalFlags) {
        extern "C" {
            fn dispatch_io_set_interval(
                channel: &DispatchIO,
                interval: u64,
                flags: DispatchIOIntervalFlags,
            );
        }
        unsafe { dispatch_io_set_interval(self, interval, flags) }
    }
}

impl DispatchWorkloop {
    /// Creates a new dispatch workloop to which workitems may be submitted.
    ///
    ///
    /// Parameter `label`: A string label to attach to the workloop.
    ///
    ///
    /// Returns: The newly created dispatch workloop.
    #[doc(alias = "dispatch_workloop_create")]
    #[must_use]
    #[inline]
    pub(crate) unsafe fn __new(label: *const c_char) -> DispatchRetained<DispatchWorkloop> {
        extern "C" {
            fn dispatch_workloop_create(label: *const c_char) -> Option<NonNull<DispatchWorkloop>>;
        }
        let ret = unsafe { dispatch_workloop_create(label) };
        let ret =
            ret.expect("function was marked as returning non-null, but actually returned NULL");
        unsafe { DispatchRetained::from_raw(ret) }
    }

    /// Creates a new inactive dispatch workloop that can be setup and then
    /// activated.
    ///
    ///
    /// Creating an inactive workloop allows for it to receive further configuration
    /// before it is activated, and workitems can be submitted to it.
    ///
    /// Submitting workitems to an inactive workloop is undefined and will cause the
    /// process to be terminated.
    ///
    ///
    /// Parameter `label`: A string label to attach to the workloop.
    ///
    ///
    /// Returns: The newly created dispatch workloop.
    #[doc(alias = "dispatch_workloop_create_inactive")]
    #[must_use]
    #[inline]
    pub(crate) unsafe fn __new_inactive(
        label: *const c_char,
    ) -> DispatchRetained<DispatchWorkloop> {
        extern "C" {
            fn dispatch_workloop_create_inactive(
                label: *const c_char,
            ) -> Option<NonNull<DispatchWorkloop>>;
        }
        let ret = unsafe { dispatch_workloop_create_inactive(label) };
        let ret =
            ret.expect("function was marked as returning non-null, but actually returned NULL");
        unsafe { DispatchRetained::from_raw(ret) }
    }

    /// Sets the autorelease frequency of the workloop.
    ///
    ///
    /// See dispatch_queue_attr_make_with_autorelease_frequency().
    /// The default policy for a workloop is
    /// DISPATCH_AUTORELEASE_FREQUENCY_WORK_ITEM.
    ///
    ///
    /// Parameter `workloop`: The dispatch workloop to modify.
    ///
    /// This workloop must be inactive, passing an activated object is undefined
    /// and will cause the process to be terminated.
    ///
    ///
    /// Parameter `frequency`: The requested autorelease frequency.
    #[doc(alias = "dispatch_workloop_set_autorelease_frequency")]
    #[inline]
    pub fn set_autorelease_frequency(
        self: &DispatchWorkloop,
        frequency: DispatchAutoReleaseFrequency,
    ) {
        extern "C" {
            fn dispatch_workloop_set_autorelease_frequency(
                workloop: &DispatchWorkloop,
                frequency: DispatchAutoReleaseFrequency,
            );
        }
        unsafe { dispatch_workloop_set_autorelease_frequency(self, frequency) }
    }
}
