#ifdef __BLOCKS__
#if __cplusplus < 201103L
#error Must build with C++11 or later
#endif
#if __has_feature(cxx_exceptions)
#error Must build without C++ exceptions
#endif
extern "C" {
#include "internal.h"
}
#if DISPATCH_DEBUG && DISPATCH_BLOCK_PRIVATE_DATA_DEBUG
#define _dispatch_block_private_data_debug(msg, ...) \
_dispatch_debug("block_private[%p]: " msg, (this), ##__VA_ARGS__)
#else
#define _dispatch_block_private_data_debug(msg, ...)
#endif
#pragma mark -
#pragma mark _dispatch_block_create
struct dispatch_block_private_data_s {
DISPATCH_BLOCK_PRIVATE_DATA_HEADER();
static void* operator new(size_t) = delete;
static void* operator new [] (size_t) = delete;
explicit inline DISPATCH_ALWAYS_INLINE dispatch_block_private_data_s(
dispatch_block_flags_t flags, voucher_t voucher,
pthread_priority_t priority, dispatch_block_t block) noexcept :
dbpd_magic(), dbpd_flags(flags), dbpd_atomic_flags(),
dbpd_performed(), dbpd_priority(priority), dbpd_voucher(voucher),
dbpd_block(block), dbpd_group(), dbpd_queue(), dbpd_thread()
{
_dispatch_block_private_data_debug("create, block: %p", dbpd_block);
}
inline DISPATCH_ALWAYS_INLINE dispatch_block_private_data_s(
dispatch_block_private_data_s const &o) noexcept :
dbpd_magic(DISPATCH_BLOCK_PRIVATE_DATA_MAGIC),
dbpd_flags(o.dbpd_flags), dbpd_atomic_flags(), dbpd_performed(),
dbpd_priority(o.dbpd_priority), dbpd_voucher(o.dbpd_voucher),
dbpd_block(), dbpd_group(), dbpd_queue(), dbpd_thread()
{
if (dbpd_voucher) voucher_retain(dbpd_voucher);
if (o.dbpd_block) dbpd_block = _dispatch_Block_copy(o.dbpd_block);
_dispatch_block_private_data_debug("copy from %p, block: %p from %p",
&o, dbpd_block, o.dbpd_block);
if (!o.dbpd_magic) return; dbpd_group = _dispatch_group_create_and_enter();
}
inline DISPATCH_ALWAYS_INLINE ~dispatch_block_private_data_s() noexcept
{
_dispatch_block_private_data_debug("destroy%s, block: %p",
dbpd_magic ? "" : " (stack)", dbpd_block);
if (dbpd_magic != DISPATCH_BLOCK_PRIVATE_DATA_MAGIC) return;
if (dbpd_group) {
if (!dbpd_performed) dispatch_group_leave(dbpd_group);
((void (*)(dispatch_group_t))dispatch_release)(dbpd_group);
}
if (dbpd_block) Block_release(dbpd_block);
if (dbpd_voucher) voucher_release(dbpd_voucher);
}
};
dispatch_block_t
_dispatch_block_create(dispatch_block_flags_t flags, voucher_t voucher,
pthread_priority_t pri, dispatch_block_t block)
{
struct dispatch_block_private_data_s dbpds(flags, voucher, pri, block);
return _dispatch_Block_copy(^{
(void)dbpds;
_dispatch_block_invoke(&dbpds);
});
}
extern "C" {
extern void DISPATCH_BLOCK_SPECIAL_INVOKE(void *)
asm("____dispatch_block_create_block_invoke");
void (*_dispatch_block_special_invoke)(void*) = DISPATCH_BLOCK_SPECIAL_INVOKE;
}
#endif // __BLOCKS__