单例dispatch_once
- 搜索
dispatch_once(dis
#ifdef __BLOCKS__
void
dispatch_once(dispatch_once_t *val, dispatch_block_t block)
{
dispatch_once_f(val, block, _dispatch_Block_invoke(block));
}
#endif
传入两个参数,onceToken
和block
,调用dispatch_once_f
传入三个参数,由block
生成的func
- 搜索
dispatch_once_f
DISPATCH_NOINLINE
void
dispatch_once_f(dispatch_once_t *val, void *ctxt, dispatch_function_t func)
{
//将传入的静态变量保存到 l
dispatch_once_gate_t l = (dispatch_once_gate_t)val;
#if !DISPATCH_ONCE_INLINE_FASTPATH || DISPATCH_ONCE_USE_QUIESCENT_COUNTER
//原子读取操作
uintptr_t v = os_atomic_load(&l->dgo_once, acquire);
//当v == DLOCK_ONCE_DONE 直接return
if (likely(v == DLOCK_ONCE_DONE)) {
return;
}
#if DISPATCH_ONCE_USE_QUIESCENT_COUNTER
if (likely(DISPATCH_ONCE_IS_GEN(v))) {
return _dispatch_once_mark_done_if_quiesced(l, v);
}
#endif
#endif
//原子性的比较赋值函数
if (_dispatch_once_gate_tryenter(l)) {
//callout func
return _dispatch_once_callout(l, ctxt, func);
}
//避免多线程影响,其他线程进来在此函数等待
return _dispatch_once_wait(l);
}
- 查看
_dispatch_once_callout
DISPATCH_NOINLINE
static void
_dispatch_once_callout(dispatch_once_gate_t l, void *ctxt,
dispatch_function_t func)
{
//调用block
_dispatch_client_callout(ctxt, func);
//设置l的值,标记block已经被执行过
_dispatch_once_gate_broadcast(l);
}
dispatch_barrier 栅栏函数
dispatch_semaphore_t 信号量
我们从dispatch_semaphore_create
开始
- 搜索
dispatch_semaphore_create
dispatch_semaphore_t
dispatch_semaphore_create(long value)
{
dispatch_semaphore_t dsema;
if (value < 0) {
return DISPATCH_BAD_INPUT;
}
//开辟内存
dsema = _dispatch_object_alloc(DISPATCH_VTABLE(semaphore),
sizeof(struct dispatch_semaphore_s));
dsema->do_next = DISPATCH_OBJECT_LISTLESS;
dsema->do_targetq = _dispatch_get_default_queue(false);
dsema->dsema_value = value;
_dispatch_sema4_init(&dsema->dsema_sema, _DSEMA4_POLICY_FIFO);
dsema->dsema_orig = value;
return dsema;
}
创建一个信号量,进行赋值然后return
。
接下来我们查看dispatch_semaphore_wait
方法。
- 搜索
dispatch_semaphore_wait
long
dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout)
{
//os_atomic_sub(&(dsema)->dsema_value, (1), acquire)
//_os_atomic_c11_op((&(dsema)->dsema_value), (1), acquire, sub, -)
//让信号量的 value - 1
long value = os_atomic_dec2o(dsema, dsema_value, acquire);
if (likely(value >= 0)) {//大于等于0时,操作成功 正常返回
return 0;
}
//特殊情况,进入长等待
return _dispatch_semaphore_wait_slow(dsema, timeout);
}
- 搜索
_dispatch_semaphore_wait_slow
DISPATCH_NOINLINE
static long
_dispatch_semaphore_wait_slow(dispatch_semaphore_t dsema,
dispatch_time_t timeout)
{
long orig;
_dispatch_sema4_create(&dsema->dsema_sema, _DSEMA4_POLICY_FIFO);
switch (timeout) {
default:
if (!_dispatch_sema4_timedwait(&dsema->dsema_sema, timeout)) {
break;
}
// Fall through and try to undo what the fast path did to
// dsema->dsema_value
case DISPATCH_TIME_NOW:
orig = dsema->dsema_value;
while (orig < 0) {
if (os_atomic_cmpxchgvw2o(dsema, dsema_value, orig, orig + 1,
&orig, relaxed)) {
return _DSEMA4_TIMEOUT();
}
}
// Another thread called semaphore_signal().
// Fall through and drain the wakeup.
case DISPATCH_TIME_FOREVER:
_dispatch_sema4_wait(&dsema->dsema_sema);
break;
}
return 0;
}
接下来查看dispatch_semaphore_signal
方法
- 搜索
dispatch_semaphore_signal
long
dispatch_semaphore_signal(dispatch_semaphore_t dsema)
{
//与之对应 这里是把 value + 1
long value = os_atomic_inc2o(dsema, dsema_value, release);
if (likely(value > 0)) {//大于0 ,就表示正常情况;return 0表示处理成功
return 0;
}
if (unlikely(value == LONG_MIN)) {
DISPATCH_CLIENT_CRASH(value,
"Unbalanced call to dispatch_semaphore_signal()");
}
//当value值不正常时,进入特殊情况 长等待
return _dispatch_semaphore_signal_slow(dsema);
}
DISPATCH_NOINLINE
long
_dispatch_semaphore_signal_slow(dispatch_semaphore_t dsema)
{
_dispatch_sema4_create(&dsema->dsema_sema, _DSEMA4_POLICY_FIFO);
_dispatch_sema4_signal(&dsema->dsema_sema, 1);
return 1;
}
dispatch_group 调度组
我们从dispatch_group_enter
开始
- 搜索
dispatch_group_create(void)
dispatch_group_t
dispatch_group_create(void)
{
return _dispatch_group_create_with_count(0);
}
- 搜索
_dispatch_group_create_with_count
DISPATCH_ALWAYS_INLINE
static inline dispatch_group_t
_dispatch_group_create_with_count(uint32_t n)
{ //开辟空间
dispatch_group_t dg = _dispatch_object_alloc(DISPATCH_VTABLE(group),
sizeof(struct dispatch_group_s));
dg->do_next = DISPATCH_OBJECT_LISTLESS;
dg->do_targetq = _dispatch_get_default_queue(false);
if (n) {//创建时传入count 为 0
os_atomic_store2o(dg, dg_bits,
(uint32_t)-n * DISPATCH_GROUP_VALUE_INTERVAL, relaxed);
os_atomic_store2o(dg, do_ref_cnt, 1, relaxed); // <rdar://22318411>
}
return dg;//直接返回
}
开辟一个空间,赋值do_next
和do_targetq
然后返回。
- 搜索
dispatch_group_enter
void
dispatch_group_enter(dispatch_group_t dg)
{
//这里和信号量一样,dg_bits - 1 初始为0 减1 变为 -1
uint32_t old_bits = os_atomic_sub_orig2o(dg, dg_bits,
DISPATCH_GROUP_VALUE_INTERVAL, acquire);
//0x00000000fffffffcULL
uint32_t old_value = old_bits & DISPATCH_GROUP_VALUE_MASK;
if (unlikely(old_value == 0)) {
_dispatch_retain(dg); //一
} //4
if (unlikely(old_value == DISPATCH_GROUP_VALUE_MAX)) {
DISPATCH_CLIENT_CRASH(old_bits,
"Too many nested calls to dispatch_group_enter()");
}//当old_value = 4 时会奔溃
}
- 搜索
dispatch_group_leave
void
dispatch_group_leave(dispatch_group_t dg)
{
//与enter相反 这里进行+1操作
uint64_t new_state, old_state = os_atomic_add_orig2o(dg, dg_state,
DISPATCH_GROUP_VALUE_INTERVAL, release);
uint32_t old_value = (uint32_t)(old_state & DISPATCH_GROUP_VALUE_MASK);
//0x00000000fffffffcULL
if (unlikely(old_value == DISPATCH_GROUP_VALUE_1)) {
old_state += DISPATCH_GROUP_VALUE_INTERVAL;//old_state += 4;
do {
new_state = old_state;
if ((old_state & DISPATCH_GROUP_VALUE_MASK) == 0) {
new_state &= ~DISPATCH_GROUP_HAS_WAITERS;
new_state &= ~DISPATCH_GROUP_HAS_NOTIFS;
} else {
new_state &= ~DISPATCH_GROUP_HAS_NOTIFS;
}
if (old_state == new_state) break;
} while (unlikely(!os_atomic_cmpxchgv2o(dg, dg_state,
old_state, new_state, &old_state, relaxed)));
return _dispatch_group_wake(dg, old_state, true);
}
if (unlikely(old_value == 0)) {
DISPATCH_CLIENT_CRASH((uintptr_t)old_value,
"Unbalanced call to dispatch_group_leave()");
}
}
与dispatch_group_enter
相反,这里状态码+1。
- 搜索
dispatch_group_notify
DISPATCH_ALWAYS_INLINE
static inline void
_dispatch_group_notify(dispatch_group_t dg, dispatch_queue_t dq,
dispatch_continuation_t dsn)
{
uint64_t old_state, new_state;
dispatch_continuation_t prev;
dsn->dc_data = dq;
_dispatch_retain(dq);//+1
//从os 下层 拿到dg的状态码
prev = os_mpsc_push_update_tail(os_mpsc(dg, dg_notify), dsn, do_next);
if (os_mpsc_push_was_empty(prev)) _dispatch_retain(dg);
os_mpsc_push_update_prev(os_mpsc(dg, dg_notify), prev, dsn, do_next);
if (os_mpsc_push_was_empty(prev)) {
os_atomic_rmw_loop2o(dg, dg_state, old_state, new_state, release, {
new_state = old_state | DISPATCH_GROUP_HAS_NOTIFS;
if ((uint32_t)old_state == 0) {
os_atomic_rmw_loop_give_up({
//当state == 0 的时候,让group苏醒
return _dispatch_group_wake(dg, new_state, false);
});
}
});
}
}
- 搜索
_dispatch_group_wake
DISPATCH_NOINLINE
static void
_dispatch_group_wake(dispatch_group_t dg, uint64_t dg_state, bool needs_release)
{
uint16_t refs = needs_release ? 1 : 0; // <rdar://problem/22318411>
if (dg_state & DISPATCH_GROUP_HAS_NOTIFS) {
dispatch_continuation_t dc, next_dc, tail;
// Snapshot before anything is notified/woken <rdar://problem/8554546>
dc = os_mpsc_capture_snapshot(os_mpsc(dg, dg_notify), &tail);
do {
dispatch_queue_t dsn_queue = (dispatch_queue_t)dc->dc_data;
next_dc = os_mpsc_pop_snapshot_head(dc, tail, do_next);
_dispatch_continuation_async(dsn_queue, dc,
_dispatch_qos_from_pp(dc->dc_priority), dc->dc_flags);
_dispatch_release(dsn_queue);
} while ((dc = next_dc));//找到相应的队列
refs++;
}
if (dg_state & DISPATCH_GROUP_HAS_WAITERS) {
_dispatch_wake_by_address(&dg->dg_gen);
}
if (refs) _dispatch_release_n(dg, refs);
}
- 搜索
_dispatch_continuation_async
这里就回到了我们熟悉的异步线程的下层函数,开始创建线程然后调用block。
- 搜索
dispatch_group_async
void
dispatch_group_async(dispatch_group_t group, dispatch_queue_t queue, dispatch_block_t block)
{
dispatch_retain(group);
dispatch_group_enter(group);
dispatch_async(queue, ^{
block();
dispatch_group_leave(group);
dispatch_release(group);
});
}
这段代码完全就是对dispatch_group_enter
和dispatch_group_leave
的封装。
细心的同学可能还会发现一段dispatch_group_async
的代码
#ifdef __BLOCKS__
void
dispatch_group_async(dispatch_group_t dg, dispatch_queue_t dq,
dispatch_block_t db)
{
dispatch_continuation_t dc = _dispatch_continuation_alloc();
uintptr_t dc_flags = DC_FLAG_CONSUME | DC_FLAG_GROUP_ASYNC;
dispatch_qos_t qos;
qos = _dispatch_continuation_init(dc, dq, db, 0, dc_flags);
_dispatch_continuation_group_async(dg, dq, dc, qos);
}
#endif
- 接着查看
_dispatch_continuation_group_async
DISPATCH_ALWAYS_INLINE
static inline void
_dispatch_continuation_group_async(dispatch_group_t dg, dispatch_queue_t dq,
dispatch_continuation_t dc, dispatch_qos_t qos)
{
dispatch_group_enter(dg);
dc->dc_data = dg;
_dispatch_continuation_async(dq, dc, qos, dc->dc_flags);
}
这里仅仅是开辟线程之前调用了dispatch_group_enter
函数,并没有看见dispatch_group_leave
函数,我们猜测是不是在执行完block的时候进行了一次dispatch_group_leave
。
在以下代码处打上断点,bt
查看当前堆栈
-
bt
-
搜索
_dispatch_client_callout
方法
可以找到这么一个方法,当type = DISPATCH_GROUP_TYPE
,callout
之后会调用一次dispatch_group_leave
唤醒当前线程。
至于为什么会调用_dispatch_continuation_with_group_invoke
方法,我们接着往下看
- 搜索
_dispatch_continuation_with_group_invoke
image.png
在_dispatch_continuation_invoke_inline
之中找到了,_dispatch_continuation_invoke_inline
是唤醒调用block
的方法,此时经过条件判断,进来的是调度组就会执行_dispatch_continuation_with_group_invoke
。