本文使用的源码是libdispatch-1008.220.2版本。
once.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| void dispatch_once(dispatch_once_t *predicate, DISPATCH_NOESCAPE dispatch_block_t block);
void _dispatch_once(dispatch_once_t *predicate, DISPATCH_NOESCAPE dispatch_block_t block) { if (DISPATCH_EXPECT(*predicate, ~0l) != ~0l) { dispatch_once(predicate, block); } else { dispatch_compiler_barrier(); } DISPATCH_COMPILER_CAN_ASSUME(*predicate == ~0l); } #undef dispatch_once #define dispatch_once _dispatch_once
void dispatch_once_f(dispatch_once_t *predicate, void *_Nullable context, dispatch_function_t function); void _dispatch_once_f(dispatch_once_t *predicate, void *_Nullable context, dispatch_function_t function) { if (DISPATCH_EXPECT(*predicate, ~0l) != ~0l) { dispatch_once_f(predicate, context, function); } else { dispatch_compiler_barrier(); } DISPATCH_COMPILER_CAN_ASSUME(*predicate == ~0l); } #undef dispatch_once_f #define dispatch_once_f _dispatch_once_f
|
由上可以简单的知道,dispatch_once 调用了 dispatch_once_f方法,
为了解释DISPATCH_EXPECT
,我把宏定义贴下面
1 2 3 4 5 6 7
| #if __GNUC__ #define DISPATCH_EXPECT(x, v) __builtin_expect((x), (v)) #define dispatch_compiler_barrier() __asm__ __volatile__("" ::: "memory") #else #define DISPATCH_EXPECT(x, v) (x) #define dispatch_compiler_barrier() do { } while (0) #endif
|
头文件中用到一个DISPATCH_EXPECT宏,这个宏展开之后其实是一个GCC内置函数__builtin_expect(exp, c),在GCC手册上是这样描述这个函数的:由于大部分程序员在分支预测方面做得很糟糕,所以 GCC 提供了这个内建函数来帮助程序员处理分支预测,优化程序。其第一个参数 exp 为一个整型表达式,这个内建函数的返回值也是这个 exp ,而 c 为一个编译期常量。这个函数的语义是:你期望 exp 表达式的值等于常量 c ,从而 GCC 为你优化程序,将符合这个条件的分支放在合适的地方
我们来看实现
once.c