美文网首页
dispatch_once深入

dispatch_once深入

作者: nadou23 | 来源:发表于2018-03-28 19:37 被阅读47次

    1.dispatch_once是用来进行一次初始化的通常我们使用dispatch_once时都是这样的

    static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
             //do something
        });
    

    2.首先要了解到dispatch_once_t是个long类型,并且编译器初始化onceToken为0,看源代码也可以知道

    typedef long dispatch_once_t;
    // A predicate for use with dispatch_once(). It must be initialized to zero.
    

    3.而对于 dispatch_once进入它的头文件发现

    #ifdef __BLOCKS__
    __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_4_0)
    DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
    DISPATCH_SWIFT3_UNAVAILABLE("Use lazily initialized globals instead")
    void
    dispatch_once(dispatch_once_t *predicate,
            DISPATCH_NOESCAPE dispatch_block_t block);
    
    DISPATCH_INLINE DISPATCH_ALWAYS_INLINE DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
    DISPATCH_SWIFT3_UNAVAILABLE("Use lazily initialized globals instead")
    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
    #endif
    
    
    

    4.其中可以发现其实 dispatch_once是_dispatch_once函数的宏,我们调用dispatch_once实际上是首先调用了_dispatch_once函数,dispatch_once函数内部大概意思就是判断DISPATCH_EXPECT(predicate, ~0l) != ~0l是否不是 -1(~0l 表示长整型0按位取反,其实就是长整型的-1),如果确实不是-1,那就执行dispatch_once(predicate, block),如果是-1,那就执行dispatch_compiler_barrier()。
    5.当然对DISPATCH_EXPECT(
    predicate, ~0l)会有疑惑,点进去看它的定义,可以看到

    #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
    
    

    从上面的判断GNUC(就是判断gcc版本的预定义宏,现在一般都是满足条件的)可以看到#define DISPATCH_EXPECT(x, v) __builtin_expect((x), (v)),它是__builtin_expect((x), (v))的宏,而对于__builtin_expect((x), (v)

    __builtin_expect(onceToken, ~0l) 当onceToken == 0时,DISPATCH_EXPECT(*predicate, ~0l) != ~0l的结果就是TRUE,执行dispatch_once(predicate, block),同时dispatch_once执行完后,onceToken就变为-1了,当你再一次从最开始执行dispatch_once时,就执行dispatch_compiler_barrier()。
    

    相关文章

      网友评论

          本文标题:dispatch_once深入

          本文链接:https://www.haomeiwen.com/subject/lzgycftx.html