Pre
- 源码分析版本:libdispatch-1173.100.2
GCD - 单例
- 老规矩分析之前带着问题:
- GCD如何保证单例中的代码只执行一次?
- 如果多次调用会有什么结果?
基本使用
//将token用static修饰可以保证其在整个程序生命周期都保持不被销毁
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSLog(@"");
});
开始往里走!
void
//实际调用的是下面这个方法。此处只留下关键部分。
dispatch_once_f(dispatch_once_t *val, void *ctxt, dispatch_function_t func)
{
// 1. 初始化一个dispatch_once_gate_t结构体l
dispatch_once_gate_t l = (dispatch_once_gate_t)val;
/* 2. 取l中的dgo_once和acquire字符串传入os_atomic_load函数处理得到v值
* 尝试过进宏定义去看,但是实在走不下去了
*大概就是创建了一个对象并存储
*如果执行过则返回1,没执行过返回0
*/
uintptr_t v = os_atomic_load(&l->dgo_once, acquire);
/*
*3.1 若v的值为1,表明已经执行过,直接返回,不作处理
*/
if (likely(v == DLOCK_ONCE_DONE)) {
return;
}
/*
* 3.2 若v不为1,进入_dispatch_once_gate_tryenter(1)函数(见下方*内部调用函数*)
*/
if (_dispatch_once_gate_tryenter(l)) {
//调用。此处函数嵌套见*代码块A*
return _dispatch_once_callout(l, ctxt, func);
}
// 等待,及一些异常判断和处理。此处见*代码块B*
return _dispatch_once_wait(l);
}
/*
*用到的宏定义
*/
#define DLOCK_ONCE_DONE (~(uintptr_t)0)
/*
* 内部调用函数
*/
static inline bool
_dispatch_once_gate_tryenter(dispatch_once_gate_t l)
{
//判断该对象是否存储过,若存储过返回false,没存储过返回true
return os_atomic_cmpxchg(&l->dgo_once, DLOCK_ONCE_UNLOCKED,
(uintptr_t)_dispatch_lock_value_for_self(), relaxed);
}
代码块A
static void
_dispatch_once_callout(dispatch_once_gate_t l, void *ctxt,
dispatch_function_t func)
{
//block执行
_dispatch_client_callout(ctxt, func);
//告诉系统执行完了,并为l对象内存地址存储加锁
_dispatch_once_gate_broadcast(l);
}
static inline void
_dispatch_once_gate_broadcast(dispatch_once_gate_t l)
{
dispatch_lock value_self = _dispatch_lock_value_for_self();
uintptr_t v;
#if DISPATCH_ONCE_USE_QUIESCENT_COUNTER
//正在操作
v = _dispatch_once_mark_quiescing(l);
#else
//操作完成
v = _dispatch_once_mark_done(l);
#endif
if (likely((dispatch_lock)v == value_self)) return;
_dispatch_gate_broadcast_slow(&l->dgo_gate, (dispatch_lock)v);
}
代码块B
//摘取关键部分
void
_dispatch_once_wait(dispatch_once_gate_t dgo)
{
dispatch_lock self = _dispatch_lock_value_for_self();
uintptr_t old_v, new_v;
dispatch_lock *lock = &dgo->dgo_gate.dgl_lock;
uint32_t timeout = 1;
for (;;) {
os_atomic_rmw_loop(&dgo->dgo_once, old_v, new_v, relaxed, {
if (likely(old_v == DLOCK_ONCE_DONE)) {
os_atomic_rmw_loop_give_up(return);
}
new_v = old_v | (uintptr_t)DLOCK_WAITERS_BIT;
if (new_v == old_v) os_atomic_rmw_loop_give_up(break);
});
if (unlikely(_dispatch_lock_is_locked_by((dispatch_lock)old_v, self))) {
//若old_v已经被加过锁会crash。
//留下疑问,什么情况下会lock recursively?
DISPATCH_CLIENT_CRASH(0, "trying to lock recursively");
}
_dispatch_thread_switch(new_v, flags, timeout++);
(void)timeout;
}
}
GCD 信号量
基本使用
//信号量创建
dispatch_semaphore_t sem = dispatch_semaphore_create(0);
//+1
dispatch_semaphore_signal(sem);
//-1 堵塞
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
开始往里走!dispatch_semaphore_create
dispatch_semaphore_t
dispatch_semaphore_create(long value){
dispatch_semaphore_t dsema;
if (value < 0) {//value必须>=0
return DISPATCH_BAD_INPUT;
}
// 初始化及变量设置。可见信号量底层是一个dispatch_object_t对象。
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;
}
开始往里走!dispatch_semaphore_signal
long
dispatch_semaphore_signal(dispatch_semaphore_t dsema)
{
/*
* 1. 信号量的值+1
*/
long value = os_atomic_inc2o(dsema, dsema_value, release);
/*
* 2.1 若value>0,直接返回0
*/
if (likely(value > 0)) {
return 0;
}
/*
* 2.2 若value == -1,crash
*/
if (unlikely(value == LONG_MIN)) {
DISPATCH_CLIENT_CRASH(value,
"Unbalanced call to dispatch_semaphore_signal()");
}
/*
* 2.3 返回1。
* 这里才是重点!
*/
return _dispatch_semaphore_signal_slow(dsema);
}
来看重点
long
_dispatch_semaphore_signal_slow(dispatch_semaphore_t dsema)
{
//1. 数据判断及异常处理。见代码块C
_dispatch_sema4_create(&dsema->dsema_sema, _DSEMA4_POLICY_FIFO);
//见代码块D
_dispatch_sema4_signal(&dsema->dsema_sema, 1);
//一通处理完之后返回1
return 1;
}
代码块C
static inline void
_dispatch_sema4_create(_dispatch_sema4_t *sema, int policy)
{
if (!_dispatch_sema4_is_created(sema)) {
//若该信号量没有被初始化过,create一波,有兴趣的话见下方*嵌套函数*
_dispatch_sema4_create_slow(sema, policy);
}
}
/*
* 相关宏定义
*/
#define _dispatch_sema4_is_created(sema) (*(sema) != MACH_PORT_NULL)
/*
* 嵌套函数
*/
void
_dispatch_sema4_create_slow(_dispatch_sema4_t *s4, int policy)
{
semaphore_t tmp = MACH_PORT_NULL;
_dispatch_fork_becomes_unsafe();
// 延迟分配信号量端口。
//这个kern_return_t就是个int类型
kern_return_t kr = semaphore_create(mach_task_self(), &tmp, policy, 0);
DISPATCH_SEMAPHORE_VERIFY_KR(kr);
if (!os_atomic_cmpxchg(s4, MACH_PORT_NULL, tmp, relaxed)) {
kr = semaphore_destroy(mach_task_self(), tmp);
DISPATCH_SEMAPHORE_VERIFY_KR(kr);
}
}
代码块D
void
_dispatch_sema4_signal(_dispatch_sema4_t *sema, long count)
{//一个do-while循环判断有无异常,并--count,意思就是走一遍没问题count为0了就不等了
do {
//这个kern_return_t就是个int类型
kern_return_t kr = semaphore_signal(*sema);
DISPATCH_SEMAPHORE_VERIFY_KR(kr);
} while (--count);
}
/*
* 相关宏定义
*/
//会给mach发送消息进行相关判断处理
#define DISPATCH_SEMAPHORE_VERIFY_KR(x) do { \
DISPATCH_VERIFY_MIG(x); \
if (unlikely((x) == KERN_INVALID_NAME)) { \
DISPATCH_CLIENT_CRASH((x), \
"Use-after-free of dispatch_semaphore_t or dispatch_group_t"); \
} else if (unlikely(x)) { \
DISPATCH_INTERNAL_CRASH((x), "mach semaphore API failure"); \
} \
} while (0)
// MIG_REPLY_MISMATCH表示:
// 1)信号处理程序没有使用异步安全API。更多信息请参阅sigaction(2)手册页。
// 2)手工制作的mach_msg*()调用失败。使用MIG。
#define DISPATCH_VERIFY_MIG(x) do { \
if ((x) == MIG_REPLY_MISMATCH) { \
_dispatch_set_crash_log_cause_and_message((x), \
"MIG_REPLY_MISMATCH"); \
_dispatch_hardware_crash(); \
} \
} while (0)
开始往里走!dispatch_semaphore_wait
long
dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout)
{
// 1. 信号量的值-1
long value = os_atomic_dec2o(dsema, dsema_value, acquire);
// 2.1 若>=0,则直接返回0
if (likely(value >= 0)) {
return 0;
}
// 2.2 若<0,进入慢速处理。见代码块E
return _dispatch_semaphore_wait_slow(dsema, timeout);
}
代码块E
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;
}
//失败,并尝试撤销快速路径对信号量要做的事
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();
}
}
// 如果有另一个线程调用dispatch_semaphore_signal()
//失败,并等待唤醒。
case DISPATCH_TIME_FOREVER:
_dispatch_sema4_wait(&dsema->dsema_sema);
break;
}
//返回0
return 0;
}
GCD 调度组
基本使用
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_queue_create("label", DISPATCH_QUEUE_CONCURRENT);
dispatch_group_enter(group);
dispatch_group_leave(group);
//内部封装dispatch_group_enter dispatch_group_leave
dispatch_group_async(group, queue, ^{
});
dispatch_group_notify(group, queue, ^{
});
开始往里走!dispatch_group_enter
void
dispatch_group_enter(dispatch_group_t dg)
{
// 该值在一个32位宽的原子上递减,这样0 -> -1跃迁的进位不会传播到上32位
uint32_t old_bits = os_atomic_sub_orig2o(dg, dg_bits,
DISPATCH_GROUP_VALUE_INTERVAL, acquire);
uint32_t old_value = old_bits & DISPATCH_GROUP_VALUE_MASK;
//若为0,则retain(参考下ARC里的retain的意思,就很好理解了)
if (unlikely(old_value == 0)) {
_dispatch_retain(dg);
}
if (unlikely(old_value == DISPATCH_GROUP_VALUE_MAX)) {
DISPATCH_CLIENT_CRASH(old_bits,
"Too many nested calls to dispatch_group_enter()");
}
}
/*
* 相关宏定义
*/
#define DISPATCH_GROUP_VALUE_MASK 0x00000000fffffffcULL
开始往里走!dispatch_group_leave
void
dispatch_group_leave(dispatch_group_t dg)
{
// 该值在64位宽的原子上递增,因此-1 -> 0跃迁的进位以原子方式递增。
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);
if (unlikely(old_value == DISPATCH_GROUP_VALUE_1)) {
old_state += DISPATCH_GROUP_VALUE_INTERVAL;
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 {
// 如果在上面的atomic_add之后再次进入组,我们不能再清除等待者位,因为我们不知道等待者是属于哪一代的
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)));
//看这里就行了!!!!!见代码块F
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()");
}
}
代码块F
static void
_dispatch_group_wake(dispatch_group_t dg, uint64_t dg_state, bool needs_release)
{
uint16_t refs = needs_release ? 1 : 0;
if (dg_state & DISPATCH_GROUP_HAS_NOTIFS) {/
dispatch_continuation_t dc, next_dc, tail;
// 在任何事情被通知/唤醒之前的快照
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);
//release(参考下ARC里的release的意思,就很好理解了)
_dispatch_release(dsn_queue);
} while ((dc = next_dc));
refs++;
}
if (dg_state & DISPATCH_GROUP_HAS_WAITERS) {
_dispatch_wake_by_address(&dg->dg_gen);
}
//release(参考下ARC里的release的意思,就很好理解了)
if (refs) _dispatch_release_n(dg, refs);
}
开始往里走!dispatch_group_async
- 问题
- 如何异步?
- 如何通知?
void
dispatch_group_async(dispatch_group_t dg, dispatch_queue_t dq,
dispatch_block_t db)
{
//1. 创建一个dispatch_continuation_t结构体并分配地址
dispatch_continuation_t dc = _dispatch_continuation_alloc();
uintptr_t dc_flags = DC_FLAG_CONSUME | DC_FLAG_GROUP_ASYNC;
dispatch_qos_t qos;
// 2. 初始化。见代码块G
qos = _dispatch_continuation_init(dc, dq, db, 0, dc_flags);
// 3. 异步执行。见代码块H
_dispatch_continuation_group_async(dg, dq, dc, qos);
}
/*
* 相关宏定义
*/
// this is set on async or for non event_handler source handlers
#define DC_FLAG_CONSUME 0x004ul
// continuation has a group in dc_data
#define DC_FLAG_GROUP_ASYNC 0x008ul
代码块G
static inline dispatch_qos_t
_dispatch_continuation_init(dispatch_continuation_t dc,
dispatch_queue_class_t dqu, dispatch_block_t work,
dispatch_block_flags_t flags, uintptr_t dc_flags)
{
void *ctxt = _dispatch_Block_copy(work);
dc_flags |= DC_FLAG_BLOCK | DC_FLAG_ALLOCATED;
if (unlikely(_dispatch_block_has_private_data(work))) {
dc->dc_flags = dc_flags;
dc->dc_ctxt = ctxt;
// will initialize all fields but requires dc_flags & dc_ctxt to be set
//这个函数中的嵌套会走到dispatch_group_leave
return _dispatch_continuation_init_slow(dc, dqu, flags);
}
dispatch_function_t func = _dispatch_Block_invoke(work);
if (dc_flags & DC_FLAG_CONSUME) {
func = _dispatch_call_block_and_release;
}
//设置优先级
return _dispatch_continuation_init_f(dc, dqu, ctxt, func, flags, dc_flags);
}
static inline dispatch_qos_t
_dispatch_continuation_init_f(dispatch_continuation_t dc,
dispatch_queue_class_t dqu, void *ctxt, dispatch_function_t f,
dispatch_block_flags_t flags, uintptr_t dc_flags)
{
pthread_priority_t pp = 0;
dc->dc_flags = dc_flags | DC_FLAG_ALLOCATED;
dc->dc_func = f;
dc->dc_ctxt = ctxt;
//在这种情况下,DISPATCH_BLOCK_HAS_PRIORITY意味着不应该传播优先级,只从有优先级的处理程序中获取优先级
if (!(flags & DISPATCH_BLOCK_HAS_PRIORITY)) {
pp = _dispatch_priority_propagate();
}
_dispatch_continuation_voucher_set(dc, flags);
return _dispatch_continuation_priority_set(dc, dqu, pp, flags);
}
代码块H
static inline void
_dispatch_continuation_group_async(dispatch_group_t dg, dispatch_queue_t dq,
dispatch_continuation_t dc, dispatch_qos_t qos)
{
//******内部实现了enter!!******
dispatch_group_enter(dg);
dc->dc_data = dg;
//异步调用
_dispatch_continuation_async(dq, dc, qos, dc->dc_flags);
}
static inline void
_dispatch_continuation_async(dispatch_queue_class_t dqu,
dispatch_continuation_t dc, dispatch_qos_t qos, uintptr_t dc_flags)
{
#if DISPATCH_INTROSPECTION
if (!(dc_flags & DC_FLAG_NO_INTROSPECTION)) {
_dispatch_trace_item_push(dqu, dc);
}
#else
(void)dc_flags;
#endif
return dx_push(dqu._dq, dc, qos);
}
/*
* 相关宏定义
*/
#define dx_push(x, y, z) dx_vtable(x)->dq_push(x, y, z)
那么这个dx_push就回到了init.c文件中的队列数组
开始往里走!dispatch_group_notify
void
dispatch_group_notify(dispatch_group_t dg, dispatch_queue_t dq,
dispatch_block_t db)
{
//1. 初始化操作
dispatch_continuation_t dsn = _dispatch_continuation_alloc();
_dispatch_continuation_init(dsn, dq, db, 0, DC_FLAG_CONSUME);
//2. 实际调用。见代码块I
_dispatch_group_notify(dg, dq, dsn);
}
代码块I
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);
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({
return _dispatch_group_wake(dg, new_state, false);
});
}
});
}
}
..dbq。累了。回头补!
来源:oschina
链接:https://my.oschina.net/u/4135139/blog/4899616