When I dive into source code of GCD (Grand Central Dispatch), I found some low-level C functions used in dispatch_block_cancel showed below
dispatch_block_cancel(dispatch_block_t db)
{
dispatch_block_private_data_t dbpd = _dispatch_block_get_data(db);
if (unlikely(!dbpd)) {
DISPATCH_CLIENT_CRASH(0, "Invalid block object passed to "
"dispatch_block_cancel()");
}
(void)os_atomic_or2o(dbpd, dbpd_atomic_flags, DBF_CANCELED, relaxed);
}
The os_atomic_or2o macro seems to set DBF_CANCELED in dbpd which is the private data of the block.
But after use gcc -E expand the macro, I can't find any setting behavior.
(void)({
__typeof__(__c11_atomic_load(((__typeof__(*((&(dbpd)->dbpd_atomic_flags))) _Atomic *)((&(dbpd)->dbpd_atomic_flags))), memory_order_relaxed)) _v = (((1u))),
_r = __c11_atomic_fetch_or(((__typeof__(*((&(dbpd)->dbpd_atomic_flags))) _Atomic *)((&(dbpd)->dbpd_atomic_flags))), _v, memory_order_relaxed);
(__typeof__(_r))(_r | _v);
});
_v is a variable inited by type of &(dbpd)->dbpd_atomic_flags, value of 1u.
_r is a variable inited by | operation between _v and &(dbpd)->dbpd_atomic_flags.
And finally do an | operation and end.
Where is the assigning code ...
Find the secret behind the macro
os_atomic_or2o, the assigning code is__c11_atomic_fetch_orwhich is__atomic_fetch_orand in GCC built_in functions referrence, this function will assign new value to the first param.