libevent源码学习(3):线程锁、条件变量(一)(锁函数、条件变量函数设置)

本文详细介绍了libevent库中线程锁和条件变量的函数结构体,包括锁函数结构体evthread_lock_callbacks及其分配、释放、加锁和解锁函数,以及条件变量函数结构体evthread_condition_callbacks及其分配、释放、信号和等待函数。文章还讨论了如何设置自定义的锁和条件变量函数,以及libevent如何使用POSIX线程函数。通过对libevent源码的分析,读者可以了解到如何在libevent中使用和定制线程同步机制。
摘要由CSDN通过智能技术生成

目录

锁与条件变量函数结构体

锁函数结构体

设置自定义的锁函数

条件变量函数结构体

设置自定义的条件变量函数

使用posix线程函数

默认的锁函数

evthread_posix_lock_alloc

evthread_posix_lock_free

evthread_posix_lock

evthread_posix_unlock

默认的条件变量函数

evthread_posix_cond_alloc

evthread_posix_cond_free

evthread_posix_cond_signal

evthread_posix_cond_wait

再探锁函数设置接口

再探条件变量函数设置接口

线程ID获取函数接口

总结


以下源码均基于libevent-2.0.21-stable。

        libevent中,使用了很多函数,而这么多的函数并不是所有都是对用户开放的,这一些函数声明都放在include文件夹下以供用户调用,而另一大部分不在其中的函数,则为libevent的内部调用函数。接下来要分析libevent的线程锁与条件变量,那么就先来看用户所能使用的接口有哪些,在include/event2文件夹下,可以看到一个thread.h的文件,因此就先从该文件入手开始分析。

锁与条件变量函数结构体

锁函数结构体

           锁对应的结构体为evthread_lock_callbacks,其定义如下:

(thread.h)

struct evthread_lock_callbacks {
   /** The current version of the locking API.  Set this to
    * EVTHREAD_LOCK_API_VERSION */
   int lock_api_version;
   /** Which kinds of locks does this version of the locking API
    * support?  A bitfield of EVTHREAD_LOCKTYPE_RECURSIVE and
    * EVTHREAD_LOCKTYPE_READWRITE.
    *
    * (Note that RECURSIVE locks are currently mandatory, and
    * READWRITE locks are not currently used.)
    **/
   unsigned supported_locktypes;
   /** Function to allocate and initialize new lock of type 'locktype'.
    * Returns NULL on failure. */   //以下都是函数指针
   void *(*alloc)(unsigned locktype);    //分配一个指定类型的锁,如果分配失败返回NULL
   /** Funtion to release all storage held in 'lock', which was created
    * with type 'locktype'. */
   void (*free)(void *lock, unsigned locktype);   //释放一个指定类型的锁,分配成功返回0,否则失败
   /** Acquire an already-allocated lock at 'lock' with mode 'mode'.
    * Returns 0 on success, and nonzero on failure. */
   int (*lock)(unsigned mode, void *lock);     //对一个已分配的锁进行加锁,锁的模式为read/write/try,获取成功返回0
   /** Release a lock at 'lock' using mode 'mode'.  Returns 0 on success,
    * and nonzero on failure. */
   int (*unlock)(unsigned mode, void *lock);   //对一个已持有的锁进行解锁,解锁成功返回0;需指定锁的模式
};

        锁结构体一共有6个变量,后面4个成员为函数指针,分别指向锁的分配(alloc)、释放(free)、上锁(lock)和解锁(unlock)四个函数,由此可见,libevent中的锁函数也是可以用户自己定制的。可以看到,这些锁函数中会用到的参数有锁变量lock、锁类型locktype以及锁模式mode,锁变量自然不必说,那么锁类型和锁模式是什么呢?

        对于当前版本的libevent,thread.h中宏定义了WRITE、READ和TRY三种模式,以及RECURSIVE和READWRITE两种类型,如下所示。

#define EVTHREAD_WRITE    0x04      //用于读写锁中的写模式

#define EVTHREAD_READ    0x08       //用于读写锁中的读模式

#define EVTHREAD_TRY    0x10      //尝试加锁模式,如果获取不到锁也不用阻塞

#define EVTHREAD_LOCKTYPE_RECURSIVE 1        //递归锁,同一线程可以多次持有同一个锁,其他线程如果想获取该锁,需要持有线程进行加锁次数的解锁,此时递归锁才能被其他线程持有

#define EVTHREAD_LOCKTYPE_READWRITE 2      //读写锁,可以多个线程同时以读模式持有同一个锁,但是只能有一个线程以写模式持有该锁,如果该锁被写模式持有,那么其他线程也无法以读模式持有该锁

        实际上还有默认的普通锁类型和模式,值为0,这里没有直接写出来,但是在后面的函数中会有所体现。

        再回到前两个成员变量中。supported_locktypes就不用说了,就是指的锁的类型。lock_api_version从字面意义上将是锁的API版本,根据上面相关的英文说明,lock_api_version的位域以及目前锁类型(当前为递归锁和读写锁)的定义反映了当前版本的libevent所支持的锁类型,并且其中还提到,目前版本只使用了递归锁,没有使用读写锁,而当前的版本由宏定义EVTHREAD_LOCK_API_VERSION确定,其定义为

#define EVTHREAD_LOCK_API_VERSION 1

        如何理解呢?根据我的理解,递归锁宏定义为1,读写锁为2,lock_api_version应当是其所支持的锁进行位或的结果就是举个例子,如果只支持递归锁,那么lock_api_version就是1,与这里相对应;如果只支持读写锁,那么lock_api_version就应该是2;如果二者都支持,那么lock_api_version就应该为3了。这样,通过lock_api_version的位域也就能反映出当前版本支持哪些lock了。因此,如果后面拓展到其他类型的锁,那么锁宏定义应当为4、8....

设置自定义的锁函数

        如同libevent的日志、错误处理以及内存管理函数一样,锁函数也可以进行定制,定制接口为evthread_set_lock_callbacks函数。其原型为:

int evthread_set_lock_callbacks(const struct evthread_lock_callbacks *); 

        原型很简单,传入一个锁函数结构体即可,调用该函数后,libevent中一旦需要使用锁的相关函数,那么就会自动调用传入的结构体中相对应的函数。该函数的实现在后面进行分析。

条件变量函数结构体

        条件变量对应结构体为evthread_condition_callbacks,其定义如下:

struct evthread_condition_callbacks {
   /** The current version of the conditions API.  Set this to
    * EVTHREAD_CONDITION_API_VERSION */
   int condition_api_version;
   /** Function to allocate and initialize a new condition variable.
    * Returns the condition variable on success, and NULL on failure.
    * The 'condtype' argument will be 0 with this API version.
    */
   void *(*alloc_condition)(unsigned condtype);     //分配并初始化一个条件变量,分配成功就返回这个条件变量,否则返回NULL,当前版本下的condtype为0
   /** Function to free a condition varia

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值