https://blog.csdn.net/weixin_30710457/article/details/96409480
首先说明GUARDED_BY(mutex_)这种用于clang编译器线程安全检查的部分不在本文讨论范围,如果需要详细了解,见此链接Thread Safety Analysis。
#if defined(__cplusplus)
#define __BEGIN_DECLS extern "C" {
#define __END_DECLS }
#else
#define __BEGIN_DECLS
#define __END_DECLS
典型的,一个C++程序包含其它语言编写的部分代码。类似的,C++编写的代码片段可能被使用在其它语言编写的代码中。不同语言编写的代码互相调用是困难的,甚至是同一种编写的代码但不同的编译器编译的代码。例如,不同语言和同种语言的不同实现可能会在注册变量保持参数和参数在栈上的布局,这个方面不一样。
为了使它们遵守统一规则,可以使用extern指定一个编译和连接规约。例如,声明C和C++标准库函数strcyp(),并指定它应该根据C的编译和连接规约来链接:
extern "C"指令非常有用,因为C和C++的近亲关系。注意:extern "C"指令中的C,表示的一种编译和连接规约,而不是一种语言。C表示符合C语言的编译和连接规约的任何语言,如Fortran、assembler等。
assert的行为依赖于一个名为NDEBUG的预处理变量的状态。如果定义了NDEBUG,则assert什么也不做。默认状态下没有定义NDEBUG,此时assert将执行运行时检查。当定义NDEBUG后再assert,assert被定义为空语句,即屏蔽; 当未定义NDEBUG,之后的每个assert都起到本应该的断言作用.。默认情况下NDEBUG没有定义。
#ifdef CHECK_PTHREAD_RETURN_VALUE
#ifdef NDEBUG
__BEGIN_DECLS
extern void __assert_perror_fail (int errnum,
const char *file,
unsigned int line,
const char *function)
noexcept __attribute__ ((__noreturn__));
__END_DECLS
#endif
#define MCHECK(ret) ({ __typeof__ (ret) errnum = (ret);
if (__builtin_expect(errnum != 0, 0))
__assert_perror_fail (errnum, __FILE__, __LINE__, __func__);})
#else // CHECK_PTHREAD_RETURN_VALUE
#define MCHECK(ret) ({ __typeof__ (ret) errnum = (ret);
assert(errnum == 0); (void) errnum;})
#endif // CHECK_PTHREAD_RETURN_VALUE
attribute_ ((noreturn))告诉编译器__assert_perror_fail`函数没有返回值也没有问题.
https://blog.csdn.net/qq_26093511/article/details/53306323
这里的__typeof__相当于typeof(),__typeof__(ret) errnum就是把errnum定义为ret这个变量的类型,而__builtin_expect是一种优化手段,__builtin_expect(A,b)意思就是A表达式大概率等于b
C语言中,FILE,func,__LINE__常用于logout,打trace,debug调试。
注意:其使用不需要定义,__FILE__指示当前文件名__func__指示当前函数名__LINE__指示运行当前文件的行数。
最后会按照FILE :LINE : func : errnum打印出错误,和assert一样,都在编译时候执行,但是好处在于它能按照格式打印出错误在哪里,便于快速排查出错误
MutexLock() : holder_(0)
{
MCHECK(pthread_mutex_init(&mutex_,NULL))
}
**pthread_mutex_init()**函数是以动态方式创建互斥锁的,函数成功时返回0,失败时返回错误码。、
MCHECK用于检查系统调用函数返回值是为为0(成功)。
void assertLocked() const ASSERT_CAPABILITY(this)
{
assert(isLockedByThisThread());
}
这是用在函数或者method后,确认是否有能力。
代码详细解析#if defined(__clang__) && (!defined(SWIG)) #define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x)) #else #define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op #endif
如果定义了clang,就会使用clang的一些attribute, 可以设置函数属性(Function Attribute )、变量属性(Variable Attribute )和类型属性(Type Attribute )。如果没有,后面就算加了attribute实际上都是宏为空(no-op)。
#ifdef CHECK_PTHREAD_RETURN_VALUE
#ifdef NDEBUG
__BEGIN_DECLS
extern void __assert_perror_fail (int errnum,
const char *file,
unsigned int line,
const char *function)
noexcept __attribute__ ((__noreturn__));
__END_DECLS
#endif
#define MCHECK(ret) ({ __typeof__ (ret) errnum = (ret);
if (__builtin_expect(errnum != 0, 0))
__assert_perror_fail (errnum, __FILE__, __LINE__, __func__);})
#else // CHECK_PTHREAD_RETURN_VALUE
#define MCHECK(ret) ({ __typeof__ (ret) errnum = (ret);
assert(errnum == 0); (void) errnum;})
#endif // CHECK_PTHREAD_RETURN_VALUE
默认情况下NDEBUG没有定义,那么默认会检查Pthread系统调用返回值是否是0(成功)。
如果定义了NDEBUG,即是在运行期间所有assert会被屏蔽。MCHECK被设置为会调用__assert_perror_fail()函数输出调试信息。
MutexLock是Mutex最基础原语的RAII,管理其创建和摧毁。
~MutexLock()
{
assert(holder_ == 0);
MCHECK(pthread_mutex_destroy(&mutex_));
}
要先确认这个锁没有人拿,再析构这个锁。
private有友元类 Conditoin和 UnassignGuard类。
UnassignGuard是由主线程(0)拿着,某一个MutexLock的Guard。
MutexLockGuard类包含一个MutexLock,其创建的时候进行加锁,这个类对象销毁的时候进行解锁。然后这个类包含的MutexLock就会对锁进行析构。MutexLockGuard对加锁解锁动作进行了封装,MutexLock对锁的初始化和析构进行了封装。



