博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【原创】libevent2中锁相关代码
阅读量:6860 次
发布时间:2019-06-26

本文共 12213 字,大约阅读时间需要 40 分钟。

hot3.png

bufferevent-internal.h
bufferevent的锁操作函数
/** Internal: Given a bufferevent, return its corresponding bufferevent_private. */// 内部使用宏// 通过 bufferevent 结构获取其所属的 bufferevent_private 结构#define BEV_UPCAST(b) EVUTIL_UPCAST((b), struct bufferevent_private, bev)#ifdef _EVENT_DISABLE_THREAD_SUPPORT    #define BEV_LOCK(b) _EVUTIL_NIL_STMT    #define BEV_UNLOCK(b) _EVUTIL_NIL_STMT#else/** Internal: Grab the lock (if any) on a bufferevent */// 内部使用宏// 对 bufferevent 上锁#define BEV_LOCK(b) do {	\    struct bufferevent_private *locking =  BEV_UPCAST(b);	\    EVLOCK_LOCK(locking->lock, 0);	\} while (0)/** Internal: Release the lock (if any) on a bufferevent */// 内部使用宏// 对 bufferevent 解锁#define BEV_UNLOCK(b) do {	\    struct bufferevent_private *locking =  BEV_UPCAST(b);	\    EVLOCK_UNLOCK(locking->lock, 0);	\} while (0)#endif
bufferevent.c
bufferevent的锁使能
// 为 bufferevent_private 创建 bufferevent 并初始化内部各结构intbufferevent_init_common(struct bufferevent_private *bufev_private,    struct event_base *base, const struct bufferevent_ops *ops, enum bufferevent_options options){...#ifndef _EVENT_DISABLE_THREAD_SUPPORT	// 如果编译时使能了线程支持    if (options & BEV_OPT_THREADSAFE) {	// 并且 bufferevent 也使能了线程支持        if (bufferevent_enable_locking(bufev, NULL) < 0) {            /* cleanup */            evbuffer_free(bufev->input);            evbuffer_free(bufev->output);            bufev->input = NULL;            bufev->output = NULL;            return -1;        }    }#endif...}
bufferevent的锁设置
// 为与 bufferevent 相关的各结构设置 lock// NOTE: 所有结构都共用 lockintbufferevent_enable_locking(struct bufferevent *bufev, void *lock){#ifdef _EVENT_DISABLE_THREAD_SUPPORT    return -1;#else    struct bufferevent *underlying;    // 首先要确保 bufev 所属的 bufferevent_private 中没有 lock    if (BEV_UPCAST(bufev)->lock)        return -1;    // 若为 socket 或 pair 类型的 bufferevent 则返回 NULL    underlying = bufferevent_get_underlying(bufev);    // 若外部未提供 lock ,但 bufev 含有底层 bufferevent    // 并且该底层 bufferevent 所属 bufferevent_private 中存在 lock 变量    // 则直接使用该 lock 做为 bufferevent 的锁    if (!lock && underlying && BEV_UPCAST(underlying)->lock) {        lock = BEV_UPCAST(underlying)->lock;        BEV_UPCAST(bufev)->lock = lock;        BEV_UPCAST(bufev)->own_lock = 0;    } else if (!lock) {	// 外部未提供 lock 且底层也无可用锁        // 则自行分配 lock 做为 bufferevent 的锁        EVTHREAD_ALLOC_LOCK(lock, EVTHREAD_LOCKTYPE_RECURSIVE);        if (!lock)            return -1;        BEV_UPCAST(bufev)->lock = lock;        BEV_UPCAST(bufev)->own_lock = 1;    } else {	// 外部提供 lock 供直接使用        BEV_UPCAST(bufev)->lock = lock;        BEV_UPCAST(bufev)->own_lock = 0;    }    // 为 input 和 output 缓冲区设置锁    evbuffer_enable_locking(bufev->input, lock);    evbuffer_enable_locking(bufev->output, lock);    if (underlying && !BEV_UPCAST(underlying)->lock)        bufferevent_enable_locking(underlying, lock);    return 0;#endif}
buffer.c
evbuffer的锁设置
// 为 evbuffer 设置 lockintevbuffer_enable_locking(struct evbuffer *buf, void *lock){#ifdef _EVENT_DISABLE_THREAD_SUPPORT    return -1;#else    // 若 evbuffer 内部已存在 lock 则直接返回    if (buf->lock)        return -1;    if (!lock) {        EVTHREAD_ALLOC_LOCK(lock, EVTHREAD_LOCKTYPE_RECURSIVE);        if (!lock)            return -1;        buf->lock = lock;        buf->own_lock = 1;    } else {        buf->lock = lock;        buf->own_lock = 0;    }    return 0;#endif}
evbuffer-internal.h
evbuffer中的锁定义
struct evbuffer {...#ifndef _EVENT_DISABLE_THREAD_SUPPORT/** A lock used to mediate access to this buffer. */    void *lock;#endif...}
event-internal.h
event_base的锁定义
struct event_base {...#ifndef _EVENT_DISABLE_THREAD_SUPPORT    /* threading support */    /** The thread currently running the event_loop for this base */    unsigned long th_owner_id;    /** A lock to prevent conflicting accesses to this event_base */    // 用于防止针对当前 event_base 冲突性访问的锁    void *th_base_lock;    /** The event whose callback is executing right now */    struct event *current_event;    /** A condition that gets signalled when we're done processing an     * event with waiters on it. */    void *current_event_cond;    /** Number of threads blocking on current_event_cond. */    int current_event_waiters;#endif...};
event.c
event_base的锁使能
struct event_base *event_base_new_with_config(const struct event_config *cfg){...#ifndef _EVENT_DISABLE_THREAD_SUPPORT  // 如果支持多线程锁    if (EVTHREAD_LOCKING_ENABLED() &&  // 测试是否锁函数为 NULL ,即 libevent 是否初始化为支持多线程        (!cfg || !(cfg->flags & EVENT_BASE_FLAG_NOLOCK))) { // 判定当前配置是否支持锁        int r;        // 申请递归锁        EVTHREAD_ALLOC_LOCK(base->th_base_lock, EVTHREAD_LOCKTYPE_RECURSIVE);        base->defer_queue.lock = base->th_base_lock;        // 申请条件变量        EVTHREAD_ALLOC_COND(base->current_event_cond);        r = evthread_make_base_notifiable(base);        if (r<0) {            event_warnx("%s: Unable to make base notifiable.", __func__);            event_base_free(base);            return NULL;        }    }#endif...}
evthread-internal.h
平台和多线程相关锁定义
#ifndef WIN32  // 非 Windows 平台/* On Windows, the way we currently make DLLs, it's not allowed for us to * have shared global structures.  Thus, we only do the direct-call-to-function * code path if we know that the local shared library system supports it. */#define EVTHREAD_EXPOSE_STRUCTS#endif#if ! defined(_EVENT_DISABLE_THREAD_SUPPORT) && defined(EVTHREAD_EXPOSE_STRUCTS) // 多线程支持+非WIN平台...#elif ! defined(_EVENT_DISABLE_THREAD_SUPPORT)  // 多线程支持+WIN平台...#else /* _EVENT_DISABLE_THREAD_SUPPORT */  // 不支持多线程...#endif
event_base锁函数
#if ! defined(_EVENT_DISABLE_THREAD_SUPPORT) && defined(EVTHREAD_EXPOSE_STRUCTS) // 多线程支持+非WIN平台.../** Acquire a lock. */// 获取锁#define EVLOCK_LOCK(lockvar,mode)	\do {	\    if (lockvar)	\    _evthread_lock_fns.lock(mode, lockvar);	\} while (0)/** Release a lock */#define EVLOCK_UNLOCK(lockvar,mode)	\do {	\    if (lockvar)	\    _evthread_lock_fns.unlock(mode, lockvar);	\} while (0).../** Lock an event_base, if it is set up for locking.  Acquires the lock    in the base structure whose field is named 'lockvar'. */// 锁定 event_base ,如果该 event_base 确实支持锁// 获取 base 结构中的锁,锁名由 lockvar 指定#define EVBASE_ACQUIRE_LOCK(base, lockvar) do {	\    EVLOCK_LOCK((base)->lockvar, 0);	\} while (0)/** Unlock an event_base, if it is set up for locking. */#define EVBASE_RELEASE_LOCK(base, lockvar) do {	\    EVLOCK_UNLOCK((base)->lockvar, 0);	\} while (0)...#elif ! defined(_EVENT_DISABLE_THREAD_SUPPORT)  // 多线程支持+WIN平台...

thread.h

#if !defined(_EVENT_DISABLE_THREAD_SUPPORT) || defined(_EVENT_IN_DOXYGEN)#define EVTHREAD_LOCK_API_VERSION 1/**   @name Types of locks         锁类型   其实这里包含第三种锁类型,即 0 值代表 普通锁   @{*//** A recursive lock is one that can be acquired multiple times at once by the * same thread.  No other process can allocate the lock until the thread that * has been holding it has unlocked it as many times as it locked it. */// 递归锁类型是指,该锁可以在同一个线程中被获取多次;其他线程无法分配该锁,直到// 持有该锁的线程对其解锁相同数量的次数#define EVTHREAD_LOCKTYPE_RECURSIVE 1/* A read-write lock is one that allows multiple simultaneous readers, but * where any one writer excludes all other writers and readers. */#define EVTHREAD_LOCKTYPE_READWRITE 2/**@}*//** This structure describes the interface a threading library uses for * locking.   It's used to tell evthread_set_lock_callbacks() how to use * locking on this platform. */// 线程锁操作函数指针结构体// 该结构用于告知 evthread_set_lock_callbacks() 在当前平台上如何使用锁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);    /** Function to release all storage held in 'lock', which was created    * with type 'locktype'. */    void (*free)(void *lock, unsigned locktype);    /** Acquire an already-allocated lock at 'lock' with mode 'mode'.    * Returns 0 on success, and nonzero on failure. */    // 以 'mode' 模式持有由 'lock' 指向的已经分配的锁;0 为获取成功,非零为失败    int (*lock)(unsigned mode, void *lock);    /** Release a lock at 'lock' using mode 'mode'.  Returns 0 on success,    * and nonzero on failure. */    int (*unlock)(unsigned mode, void *lock);};/** Sets a group of functions that Libevent should use for locking. * For full information on the required callback API, see the * documentation for the individual members of evthread_lock_callbacks. * * Note that if you're using Windows or the Pthreads threading library, you * probably shouldn't call this function; instead, use * evthread_use_windows_threads() or evthread_use_posix_threads() if you can. */int evthread_set_lock_callbacks(const struct evthread_lock_callbacks *);...#if (defined(WIN32) && !defined(_EVENT_DISABLE_THREAD_SUPPORT)) || defined(_EVENT_IN_DOXYGEN)/** Sets up Libevent for use with Windows builtin locking and thread ID    functions.  Unavailable if Libevent is not built for Windows.    @return 0 on success, -1 on failure. */int evthread_use_windows_threads(void);           // windows 上的锁使能/**   Defined if Libevent was built with support for evthread_use_windows_threads()*/#define EVTHREAD_USE_WINDOWS_THREADS_IMPLEMENTED 1#endif#if defined(_EVENT_HAVE_PTHREADS) || defined(_EVENT_IN_DOXYGEN)/** Sets up Libevent for use with Pthreads locking and thread ID functions.    Unavailable if Libevent is not build for use with pthreads.  Requires    libraries to link against Libevent_pthreads as well as Libevent.    令 libevent 可以使用 pthread 锁和相应的获取线程 id 的函数    如果构建 libevent 时候不支持 pthread 则无法使用该函数    使用时要求链接 libevent_pthreads 库和 libevent 库    @return 0 on success, -1 on failure. */int evthread_use_pthreads(void);               // linux 上的锁使能/** Defined if Libevent was built with support for evthread_use_pthreads() */#define EVTHREAD_USE_PTHREADS_IMPLEMENTED 1#endif/** Enable debugging wrappers around the current lock callbacks.  If Libevent * makes one of several common locking errors, exit with an assertion failure. * * If you're going to call this function, you must do so before any locks are * allocated. **/void evthread_enable_lock_debuging(void);#endif /* _EVENT_DISABLE_THREAD_SUPPORT */
whatsnew-2.0.txt
2.8. evthread_* functions for thread-safe structures.  Libevent structures can now be built with locking support.  This code  makes it safe to add, remove, and activate events on an event base from a  different thread.  (Previously, if you wanted to write multithreaded code  with Libevent, you could only an event_base or its events in one thread at  a time.)  If you want threading support and you're using pthreads, you can just  call evthread_use_pthreads().  (You'll need to link against the  libevent_pthreads library in addition to libevent_core.  These functions are  not in libevent_core.)  If you want threading support and you're using Windows, you can just  call evthread_use_windows_threads().  If you are using some locking system besides Windows and pthreads, You  can enable this on a per-event-base level by writing functions to  implement mutexes, conditions, and thread IDs, and passing them to  evthread_set_lock_callbacks and related functions in event2/thread.h.  Once locking functions are enabled, every new event_base is created with a  lock.  You can prevent a single event_base from being built with a lock  disabled by using the EVENT_BASE_FLAG_NOLOCK flag in its  event_config.  If an event_base is created with a lock, it is safe to call  event_del, event_add, and event_active on its events from any thread.  The  event callbacks themselves are still all executed from the thread running  the event loop.  To make an evbuffer or a bufferevent object threadsafe, call its  *_enable_locking() function.  The HTTP api is not currently threadsafe.  To build Libevent with threading support disabled, pass  --disable-thread-support to the configure script.

转载于:https://my.oschina.net/moooofly/blog/500209

你可能感兴趣的文章
innodb 的预读
查看>>
redis slaveof自己会发生什么
查看>>
php实现基本数据结构之链表
查看>>
真正理解"CSS选择器的优先级"
查看>>
mysql技巧
查看>>
Linux系统安装mysql,jdk,tomcat等软件
查看>>
Vue-cli3 项目在安卓低版本系统和 IE 上白屏问题解决
查看>>
[译] 你正在阅读的用户体验文章是不是在向你进行推销?
查看>>
RQPro 公募FOF策略实例——晨星基金筛选和风险平价配置
查看>>
我的前端2019面试指引
查看>>
iOS热更新实现方式
查看>>
创建型模式 工厂模式
查看>>
最新安装CocoaPods教程
查看>>
Swizzling Method
查看>>
React同构踩坑记录
查看>>
教你用Python如何实现微信自动回复功能,机器人自动对话!
查看>>
使用var定义变量和不使用的区别
查看>>
React两个bug踩坑
查看>>
vue引入mxGrpah
查看>>
合并冲突 - 每天三分钟玩转Git(三)
查看>>