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_or
which is__atomic_fetch_or
and in GCC built_in functions referrence, this function will assign new value to the first param.