Linux多定时器实现之三——Windows和Linux通用版
支持windows和linux。
支持秒以下定时器。
/*********************************************************************** * Copyright (c) 2018 pepstack, pepstack.com * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * * 2. Altered source versions must be plainly marked as such, and must not * be misrepresented as being the original software. * * 3. This notice may not be removed or altered from any source distribution. ***********************************************************************/ /*********************************************************************** * mul_wheel_timer.h * multiply wheel timer for linux and windows * * 多定时器的工业级实现, 支持时间单位自定义: * Linux: 微秒级 * Windows: 毫秒级 * * refer: * http://blog.csdn.net/zhangxinrun/article/details/5914191 * https://linux.die.net/man/2/setitimer * * author: [email protected] * * create: 2018-02-03 11:00 * update: 2018-02-04 **********************************************************************/ #ifndef MUL_WHEEL_TIMER_H_INCLUDED #define MUL_WHEEL_TIMER_H_INCLUDED #if defined(__cplusplus) extern "C" { #endif #if defined _MSC_VER || WIN32 #undef MWT_OS_LINUX #define MWT_OS_WINDOWS #pragma message("build for windows ...") #else #undef MWT_OS_WINDOWS #define MWT_OS_LINUX #pragma message("build for linux ...") #endif /** * thread lock */ #ifdef MWT_OS_WINDOWS // Windows // https://msdn.microsoft.com/en-us/library/windows/desktop/ms687003(v=vs.85).aspx #include <windows.h> #include <process.h> #if _WIN32_WINNT < 0x0500 #undef _WIN32_WINNT #define _WIN32_WINNT 0x0500 #pragma message("windows version is too low") #endif typedef CRITICAL_SECTION thread_lock_t; typedef LONGLONG mwt_bigint_t; typedef LONGLONG volatile mwt_counter_t; typedef struct itimerval { struct timeval it_value; struct timeval it_interval; } itimerval; #define __disable_warning_unused_static static \ static inline void bzero(void * pv, size_t size) { memset(pv, 0, size); } /* CriticalSection */ static inline int threadlock_init(thread_lock_t *lock) { InitializeCriticalSection(lock); return 0; } #define threadlock_fini(lock) DeleteCriticalSection(lock) static inline int threadlock_enter(thread_lock_t *lock) { EnterCriticalSection(lock); return 0; } #define threadlock_tryenter(lock) (TryEnterCriticalSection(lock)? 0:(-1)) #define threadlock_leave(lock) LeaveCriticalSection(lock) /* refcount */ #define __interlock_add(add) InterlockedIncrement64(add) #define __interlock_sub(sub) InterlockedDecrement64(sub) #define __interlock_release(val) InterlockedExchange64(val, 0) void __stdcall win_sigalrm_handler (PVOID lpParam, BOOLEAN TimerOrWaitFired); #else /* linux */ #include <pthread.h> #include <unistd.h> #include <sys/time.h> typedef pthread_mutex_t thread_lock_t; typedef int64_t mwt_bigint_t; #define __disable_warning_unused_static __attribute__((used)) static \ /* pthread mutex */ #define threadlock_init(lock) pthread_mutex_init(lock, 0) #define threadlock_fini(lock) pthread_mutex_destroy(lock) #define threadlock_enter(lock) pthread_mutex_lock(lock) #define threadlock_tryenter(lock) pthread_mutex_trylock(lock) #define threadlock_leave(lock) pthread_mutex_unlock(lock) /* refcount */ #define __interlock_add(add) __sync_add_and_fetch(add, 1) #define __interlock_sub(sub) __sync_sub_and_fetch(sub, 1) #define __interlock_release(val) __sync_lock_release(val) __disable_warning_unused_static void sigalarm_handler(int signo); #endif #include <stdint.h> #include <time.h> #include "dhlist.h" /*********************************************************************** * 多定时器是否支持毫秒级? * * 下面声明 多定时器不支持毫秒级: * * #define MWTIMER_MILLI_SECOND 0 * #include <mul_wheel_timer.h> * **********************************************************************/ #ifndef MWTIMER_MILLI_SECOND # define MWTIMER_MILLI_SECOND 1000 #endif /*********************************************************************** * 多定时器是否支持微秒级? * * 下面声明 多定时器不支持微秒级: * * #define MWTIMER_MICRO_SECOND 0 * #include <mul_wheel_timer.h> * **********************************************************************/ #ifndef MWTIMER_MICRO_SECOND # define MWTIMER_MICRO_SECOND 1000000 #endif #ifdef MWT_OS_WINDOWS /* windows 不支持微秒级的定时器, 取消之 */ #undef MWTIMER_MICRO_SECOND #endif /*********************************************************************** * 是否打印信息? * * 下面声明 不包含打印信息 (正式使用情况下) * * #define MWTIMER_PRINTF 0 * #include <mul_wheel_timer.h> * **********************************************************************/ #ifndef MWTIMER_PRINTF # define MWTIMER_PRINTF 0 #endif /*********************************************************************** * MWTIMER_HASHLEN_MAX * * 定义 hash 桶的大小 (2^n -1) = [255, 1023, 4095, 8191] * 可以根据需要在编译时指定。桶越大,查找速度越快。 **********************************************************************/ #ifndef MWTIMER_HASHLEN_MAX # define MWTIMER_HASHLEN_MAX 1023 #endif /*********************************************************************** * 是否使用双链表:如果不需要按次序遍历定时器不要启用它 * * MWTIMER_HAS_DLIST == 1 * use dlist for traversing by sequence * * MWTIMER_HAS_DLIST == 0 * DONOT use dlist since we need not traversing by sequence **********************************************************************/ #define MWTIMER_HAS_DLIST 0 typedef mwt_bigint_t mwt_eventid_t; typedef mwt_eventid_t * mwt_event_hdl; typedef enum { mwt_timeunit_sec = 0 #if MWTIMER_MILLI_SECOND == 1000 ,mwt_timeunit_msec = 1 #endif #if MWTIMER_MICRO_SECOND == 1000000 ,mwt_timeunit_usec = 2 #endif } mwt_timeunit_t; typedef struct mwt_event_t { mwt_eventid_t eventid; /* 引用计数: 0 删除, 1 保留 */ mwt_counter_t refc; void *eventarg; int (*timer_event_cb) (mwt_event_hdl eventhdl, void *eventarg, void *lpParameter); mwt_counter_t on_counter; /* 指定定时器首次激发时间和以后每次间隔激发时间 */ struct itimerval value; int hash; /** dhlist node */ #if MWTIMER_HAS_DLIST == 1 struct list_head i_list; #endif struct hlist_node i_hash; } mwt_event_t; typedef struct mul_wheel_timer_t { mwt_eventid_t volatile eventid; mwt_counter_t counter; thread_lock_t lock; /** * 定时器状态: * 1: 启动. (windows: status== 1) * 0: 暂停 */ int status; /** 最小时间单元值: 微秒 */ mwt_bigint_t timeunit_usec; mwt_timeunit_t timeunit_type; struct itimerval value; #ifdef MWT_OS_LINUX struct itimerval ovalue; void (* old_sigalarm)(int); void (* new_sigalarm)(int); #endif #ifdef MWT_OS_WINDOWS HANDLE hTimerQueue; #endif void * lpParameter; /** dhlist for timer entry */ #if MWTIMER_HAS_DLIST == 1 struct list_head dlist; #endif struct hlist_head hlist[MWTIMER_HASHLEN_MAX + 1]; } mul_wheel_timer_t; /* global timer variable for one linux process */ __disable_warning_unused_static struct mul_wheel_timer_t mulwheeltimer; __disable_warning_unused_static inline void free_timer_event (struct mwt_event_t * event) { #if MWTIMER_PRINTF == 1 printf("\033[32m-delete event_%llu\033[0m\n", (unsigned long long) event->eventid); #endif free(event); } __disable_warning_unused_static inline mwt_event_t * mul_handle_cast_event (mwt_event_hdl eventhdl) { struct mwt_event_t * event = CONTAINER_OF(eventhdl, struct mwt_event_t, eventid); return event; } __disable_warning_unused_static inline mwt_bigint_t mwt_hash_on_counter (mul_wheel_timer_t * mwt, mwt_bigint_t timeval_usec, int *hash) { mwt_bigint_t on_counter = (mwt_bigint_t) (timeval_usec / mwt->timeunit_usec + mwt->counter); *hash = (on_counter & MWTIMER_HASHLEN_MAX); #if MWTIMER_PRINTF == 1 printf(" * \033[36m on_counter=%" PRI64d ", hash=%d\033[0m\n", on_counter, (*hash)); #endif return on_counter; } __disable_warning_unused_static int timer_select_sleep (int sec, int ms) { if (sec || ms) { struct timeval tv = {0}; tv.tv_sec = sec; tv.tv_usec = ms * MWTIMER_MILLI_SECOND; return select (0, NULL, NULL, NULL, &tv); } else { return 0; } } /** * mul_wheel_timer_init * * 初始化定时器。如果初始化不成功,不能使用定时器。 * * params: * timeunit - time unit: second, millisecond or microsecond (for linux) * timeintval - The period of the timer, in timeunit. * If this parameter is zero, the timer is signaled once. * If this parameter is greater than zero, the timer is periodic. * A periodic timer automatically reactivates each time the period * elapses, until the timer is canceled. * delay - The amount of time in timeunit relative to the current time that * must elapse before the timer is signaled for the first time. * start - only for linux: * = 0 (do not start timer); * = 1 (start immediately when init success) * * lpParameter - A single parameter value that will be passed to the callback function. * * returns: * 0: success 初始化成功 * -1: error 初始化失败 */ __disable_warning_unused_static int mul_wheel_timer_init (mwt_timeunit_t timeunit, unsigned int timeintval, unsigned int delay, void *timerParameter ,int start) { int i, err; bzero(&mulwheeltimer, sizeof(struct mul_wheel_timer_t)); mulwheeltimer.eventid = 1; #if MWTIMER_HAS_DLIST == 1 INIT_LIST_HEAD(&mulwheeltimer.dlist); #endif for (i = 0; i <= MWTIMER_HASHLEN_MAX; i++) { INIT_HLIST_HEAD(&mulwheeltimer.hlist[i]); } err = threadlock_init(&mulwheeltimer.lock); if (err) { /* nerver run to this ! */ #if MWTIMER_PRINTF == 1 printf("[mwt:error(%d)] threadlock_init: %s.\n", err, strerror(err)); #endif return (-1); } err = threadlock_enter(&mulwheeltimer.lock); if (err) { #if MWTIMER_PRINTF == 1 printf("[mwt:error(%d)] threadlock_enter: %s.\n", err, strerror(err)); #endif return (-1); } #ifdef MWT_OS_LINUX if ( (mulwheeltimer.old_sigalarm = signal(SIGALRM, sigalarm_handler)) == SIG_ERR ) { threadlock_fini(&mulwheeltimer.lock); #if MWTIMER_PRINTF == 1 printf("[mwt:error(%d)] signal: %s.\n", errno, strerror(errno)); #endif return (-1); } #endif #ifdef MWT_OS_LINUX mulwheeltimer.new_sigalarm = sigalarm_handler; #endif if (timeunit == mwt_timeunit_sec) { /** 定义首次激发延迟时间: setitimer 之后 timeval_delay 首次激发 */ mulwheeltimer.value.it_value.tv_sec = delay; mulwheeltimer.value.it_value.tv_usec = 0; /** 定义间隔激发时间: 首次激发之后每隔 timeval_interval 激发 */ mulwheeltimer.value.it_interval.tv_sec = timeintval; mulwheeltimer.value.it_interval.tv_usec = 0; } #if MWTIMER_MILLI_SECOND == 1000 /** 如果支持毫秒定时器 */ else if (timeunit == mwt_timeunit_msec) { /** 定义首次激发延迟时间: setitimer 之后 timeval_delay 首次激发 */ mulwheeltimer.value.it_value.tv_sec = delay / MWTIMER_MILLI_SECOND; mulwheeltimer.value.it_value.tv_usec = (delay % MWTIMER_MILLI_SECOND) * MWTIMER_MILLI_SECOND; /** 定义间隔激发时间: 首次激发之后每隔 timeval_interval 激发 */ mulwheeltimer.value.it_interval.tv_sec = timeintval / MWTIMER_MILLI_SECOND; mulwheeltimer.value.it_interval.tv_usec = (timeintval % MWTIMER_MILLI_SECOND) * MWTIMER_MILLI_SECOND; } #endif #if MWTIMER_MICRO_SECOND == 1000000 /** 如果支持微秒定时器 */ else if (timeunit == mwt_timeunit_usec) { mulwheeltimer.value.it_value.tv_sec = delay / MWTIMER_MICRO_SECOND; mulwheeltimer.value.it_value.tv_usec = (delay % MWTIMER_MICRO_SECOND) * MWTIMER_MICRO_SECOND; /** 定义间隔激发时间: 首次激发之后每隔 timeval_interval 激发 */ mulwheeltimer.value.it_interval.tv_sec = timeintval / MWTIMER_MICRO_SECOND; mulwheeltimer.value.it_interval.tv_usec = (timeintval % MWTIMER_MICRO_SECOND) * MWTIMER_MICRO_SECOND; } #endif else { #ifdef MWT_OS_LINUX signal(SIGALRM, mulwheeltimer.old_sigalarm); #endif threadlock_fini(&mulwheeltimer.lock); #if MWTIMER_PRINTF == 1 printf("[mwt:error] invalid timeunit: %d.", timeunit); #endif return (-1); } /** 时间单位:秒,毫秒,微秒 */ mulwheeltimer.timeunit_type = timeunit; /** 自动转化为微妙的时间单元 */ mulwheeltimer.timeunit_usec = mulwheeltimer.value.it_interval.tv_usec + mulwheeltimer.value.it_interval.tv_sec * 1000000; #if MWTIMER_PRINTF == 1 printf("[] timeunit=%" PRId64 " microseconds.\n", mulwheeltimer.timeunit_usec); #endif #ifdef MWT_OS_LINUX if (start) { #endif #ifdef MWT_OS_WINDOWS if (1) { #endif err = -1; #ifdef MWT_OS_LINUX err = setitimer(ITIMER_REAL, &mulwheeltimer.value, &mulwheeltimer.ovalue); #endif #ifdef MWT_OS_WINDOWS do { DWORD delay_ms = (DWORD) (mulwheeltimer.value.it_value.tv_sec * 1000 + mulwheeltimer.value.it_value.tv_usec / 1000); DWORD interval_ms = (DWORD) (mulwheeltimer.value.it_interval.tv_sec * 1000 + mulwheeltimer.value.it_interval.tv_usec / 1000); HANDLE hTimer; // Create the timer queue HANDLE hTimerQueue = CreateTimerQueue(); if (! hTimerQueue) { printf("CreateTimerQueue failed (%d)\n", GetLastError()); threadlock_fini(&mulwheeltimer.lock); return (-1); } // Set a timer to call the timer routine in 10 seconds. if (! CreateTimerQueueTimer(&hTimer, hTimerQueue, (WAITORTIMERCALLBACK) win_sigalrm_handler, timerParameter, (DWORD) delay_ms, (DWORD) interval_ms, WT_EXECUTEDEFAULT)) { printf("CreateTimerQueueTimer failed (%d)\n", GetLastError()); err = -1; } else { // Success mulwheeltimer.hTimerQueue = hTimerQueue; mulwheeltimer.lpParameter = timerParameter; err = 0; } } while(0); #endif if (! err) { /** 定时器成功创建并启动 */ mulwheeltimer.status = 1; threadlock_leave(&mulwheeltimer.lock); #if MWTIMER_PRINTF == 1 printf("[mwt:info] mul_wheel_timer_init success.\n"); #endif return 0; } else { /** 定时器创建但启动失败 */ mulwheeltimer.status = 0; #ifdef MWT_OS_LINUX /** 定时器不可用,自动销毁 */ signal(SIGALRM, mulwheeltimer.old_sigalarm); #endif #ifdef MWT_OS_WINDOWS DeleteTimerQueue(mulwheeltimer.hTimerQueue); #endif threadlock_fini(&mulwheeltimer.lock); #if MWTIMER_PRINTF == 1 printf("[mwt:error] mul_wheel_timer_init failed. setitimer error(%d): %s.\n", err, strerror(err)); #endif return (-1); } } else { /** 定时器成功创建, 但不要求启动 */ mulwheeltimer.status = 0; threadlock_leave(&mulwheeltimer.lock); #if MWTIMER_PRINTF == 1 printf("[mwt:info] mul_wheel_timer_init success without starting.\n"); #endif #ifdef MWT_OS_WINDOWS // Windows 不支持随后启动定时器 #pragma message ("warnings: windows always start timer when init success") #endif return 0; } } /** * mul_wheel_timer_start * 启动定时器,仅对Linux有效。Windows自动启动定时器。 * * returns: * 0: success 成功启动 * 1: sfalse 已经启动 * -1: error 启动失败 */ __disable_warning_unused_static int mul_wheel_timer_start (void) { #ifdef MWT_OS_WINDOWS #pragma message("windows always return success(0) for this.") return 0; #endif #ifdef MWT_OS_LINUX int err; err = threadlock_tryenter(&mulwheeltimer.lock); if (err) { /** 多线程锁定失败 */ #if MWTIMER_PRINTF == 1 printf("[mwt:error(%d)] threadlock_tryenter: %s\n", err, strerror(err)); #endif return (-1); } if (mulwheeltimer.status == 1) { /** 已经启动 */ threadlock_leave(&mulwheeltimer.lock); #if MWTIMER_PRINTF == 1 printf("[mwt:warn] already start.\n"); #endif return 1; } err = setitimer(ITIMER_REAL, &mulwheeltimer.value, &mulwheeltimer.ovalue); if (! err) { /** 定时器成功启动 */ mulwheeltimer.status = 1; threadlock_leave(&mulwheeltimer.lock); #if MWTIMER_PRINTF == 1 printf("[mwt:info] mul_wheel_timer_start success.\n"); #endif return 0; } else { /** 定时器启动失败 */ mulwheeltimer.status = 0; threadlock_leave(&mulwheeltimer.lock); #if MWTIMER_PRINTF == 1 printf("[mwt:error] mul_wheel_timer_start. setitimer error(%d): %s.\n", err, strerror(err)); #endif return (-1); } #endif } /** * mul_wheel_timer_destroy * * returns: * 0: success * -1: failed. * use strerror(errno) for error message. */ __disable_warning_unused_static int mul_wheel_timer_destroy (void) { int err; err = threadlock_enter(&mulwheeltimer.lock); if (err) { #if MWTIMER_PRINTF == 1 printf("[mwt] threadlock_enter error(%d): %s\n", err, strerror(err)); #endif return (-1); } #ifdef MWT_OS_LINUX if ((signal(SIGALRM, mulwheeltimer.new_sigalarm)) == SIG_ERR) { threadlock_leave(&mulwheeltimer.lock); #if MWTIMER_PRINTF == 1 printf("[mwt] destroy failed. signal error.\n"); #endif return (-1); } /** 恢复进程原有的定时器 */ err = setitimer(ITIMER_REAL, &mulwheeltimer.ovalue, &mulwheeltimer.value); if (err < 0) { threadlock_leave(&mulwheeltimer.lock); #if MWTIMER_PRINTF == 1 printf("[mwt] destroy failed. setitimer error(%d): %s.\n", errno, strerror(errno)); #endif return (-1); } #endif #ifdef MWT_OS_WINDOWS // Delete all timers in the timer queue. if (! DeleteTimerQueue(mulwheeltimer.hTimerQueue)) { printf("DeleteTimerQueue failed (%d)\n", GetLastError()); threadlock_leave(&mulwheeltimer.lock); return (-1); } #endif /** 清空定时器链表 */ #if MWTIMER_HAS_DLIST == 1 do { struct list_head *list, *node; list_for_each_safe(list, node, &mulwheeltimer.dlist) { struct mwt_event_t * event = list_entry(list, struct mwt_event_t, i_list); hlist_del(&event->i_hash); list_del(&event->i_list); free_timer_event(event); } } while(0); #else do { int hash; struct hlist_node *hp, *hn; for (hash = 0; hash <= MWTIMER_HASHLEN_MAX; hash++) { hlist_for_each_safe(hp, hn, &mulwheeltimer.hlist[hash]) { struct mwt_event_t * event = hlist_entry(hp, struct mwt_event_t, i_hash); hlist_del(&event->i_hash); free_timer_event(event); } } } while(0); #endif threadlock_fini(&mulwheeltimer.lock); bzero(&mulwheeltimer, sizeof(struct mul_wheel_timer_t)); #if MWTIMER_PRINTF == 1 printf("[mwt] destroy success.\n"); #endif return(0); } /** * mul_wheel_timer_set_event * 设置 event timer * * params: * delay - 指定首次激发的时间:当前定时器首次启动之后多少时间激发 event: * 0 : 立即激发 * > 0 : 延迟时间 * * interval - 首次激发 event 之后间隔多久激发: * 0 : 不激发 * > 0 : 间隔多久时间激发 * * count: 最多激发次数 * MUL_WHEEL_TIMER_EVENT_INFINITE: 永久激发 * > 0 : 次数 * * returns: * > 0: mwt_eventid_t, success * < 0: failed */ #define MUL_WHEEL_TIMER_EVENT_ONEOFF (1) #define MUL_WHEEL_TIMER_EVENT_INFINITE (-1) __disable_warning_unused_static mwt_eventid_t mul_wheel_timer_set_event (mwt_bigint_t delay, mwt_bigint_t interval, mwt_bigint_t count, int (*on_event_cb)(mwt_event_hdl eventhdl, void *eventarg, void *timerarg), void *eventarg) { int err, hash; mwt_bigint_t on_counter; mwt_event_t *new_event; mwt_bigint_t delay_usec = 0; mwt_bigint_t interval_usec = 0; if (count == MUL_WHEEL_TIMER_EVENT_INFINITE) { count = INT64_MAX; } if (delay < 0 || interval < 0 || count <= 0) { /** 无效的定时器 */ return (-2); } if (mulwheeltimer.timeunit_type == mwt_timeunit_sec) { delay_usec = delay * 1000000; interval_usec = interval * 1000000; } #if MWTIMER_MILLI_SECOND == 1000 else if (mulwheeltimer.timeunit_type == mwt_timeunit_msec) { delay_usec = delay * MWTIMER_MILLI_SECOND; interval_usec = interval * MWTIMER_MILLI_SECOND; } #endif #if MWTIMER_MICRO_SECOND == 1000000 else if (mulwheeltimer.timeunit_type == mwt_timeunit_usec) { delay_usec = delay; interval_usec = interval; } #endif if (delay_usec == 0 && interval_usec == 0) { /** 无效的定时器 */ return (-2); } err = threadlock_tryenter(&mulwheeltimer.lock); if (err) { /** 多线程锁定失败 */ #if MWTIMER_PRINTF == 1 printf("[mwt] threadlock_tryenter error(%d): %s\n", err, strerror(err)); #endif return (-1); } /** * 当 mulwheeltimer.counter == on_counter 时激发 * 因此设置以 on_counter 为 hash 键保存 event */ on_counter = mwt_hash_on_counter(&mulwheeltimer, delay_usec, &hash); new_event = (mwt_event_t *) malloc(sizeof(mwt_event_t)); if (! new_event) { /** out of memory */ threadlock_leave(&mulwheeltimer.lock); return (-4); } bzero(new_event, sizeof(mwt_event_t)); new_event->eventid = mulwheeltimer.eventid++; new_event->on_counter = on_counter; /** 首次激发时间 */ new_event->value.it_value.tv_sec = (long) (delay_usec / 1000000); new_event->value.it_value.tv_usec = (long) (delay_usec % 1000000); /** 间隔激发时间 */ new_event->value.it_interval.tv_sec = (long) (interval_usec / 1000000); new_event->value.it_interval.tv_usec = (long) (interval_usec % 1000000); new_event->hash = hash; /** 设置回调参数和函数,回调函数由用户自己实现 */ new_event->eventarg = eventarg; new_event->timer_event_cb = on_event_cb; #if MWTIMER_PRINTF == 1 //printf("\033[31m+create event_%" PRI64d "\033[0m\n", new_event->eventid); //printf("\033[31m+create event_%" PRI64d ". (%d : %d)\033[0m\n", new_event->eventid, // (int) new_event->value.it_value.tv_sec, (int) new_event->value.it_interval.tv_sec); #endif #if MWTIMER_HAS_DLIST == 1 /** 串入长串 */ list_add(&new_event->i_list, &mulwheeltimer.dlist); #endif /** 串入HASH短串 */ hlist_add_head(&new_event->i_hash, &mulwheeltimer.hlist[hash]); /** 设置引用计数为 1 */ new_event->refc = count; #if MWTIMER_PRINTF == 1 // 演示如何删除自身: ////hlist_del(&new_event->i_hash); ////list_del(&new_event->i_list); ////free_timer_event(new_event); #endif threadlock_leave(&mulwheeltimer.lock); return new_event->eventid; } /** * mul_wheel_timer_remove_event * 从多定时器中删除事件。该调用仅仅标记事件要删除。真正删除的行为由系统决定。 * * returns: * 0: success * -1: failed. */ __disable_warning_unused_static int mul_wheel_timer_remove_event (mwt_event_hdl eventhdl) { mwt_event_t * event = mul_handle_cast_event(eventhdl); #if MWTIMER_PRINTF == 1 printf("remove event-%lld\n", (long long) event->eventid); #endif /** 设置引用计数为 0,当有事件触发时自动删除 */ __interlock_release(&event->refc); return 0; } /** * mul_wheel_timer_fire_event * 根据当前激发的 counter 查找 event * * params: * on_counter - 当前激发的计数器 * * returns: * number of events have been fired */ __disable_warning_unused_static int mul_wheel_timer_fire_event (mwt_bigint_t fire_counter, void * lpParamter) { struct hlist_node *hp; struct hlist_node *hn; int num_events_fired = 0; int hash = (int) (fire_counter & MWTIMER_HASHLEN_MAX); hlist_for_each_safe(hp, hn, &mulwheeltimer.hlist[hash]) { struct mwt_event_t * event = hlist_entry(hp, struct mwt_event_t, i_hash); if (event->on_counter == fire_counter) { /** 首先从链表中删除自己 */ hlist_del(&event->i_hash); #if MWTIMER_HAS_DLIST == 1 list_del(&event->i_list); #endif /** 激发事件回调函数 */ event->timer_event_cb(&event->eventid, event->eventarg, lpParamter); num_events_fired++; if (__interlock_sub(&event->refc) <= 0) { /** 要求删除事件 */ free_timer_event(event); } else { if (event->value.it_interval.tv_sec == 0) { /* 只使用一次, 下次不再激发,删除事件 */ free_timer_event(event); } else { event->on_counter = mwt_hash_on_counter(&mulwheeltimer, event->value.it_interval.tv_sec * 1000000 + event->value.it_interval.tv_usec, &event->hash); #if MWTIMER_HAS_DLIST == 1 /** 串入长串 */ list_add(&event->i_list, &mulwheeltimer.dlist); #endif /** 串入HASH短串 */ hlist_add_head(&event->i_hash, &mulwheeltimer.hlist[event->hash]); } } } } return num_events_fired; } #ifdef MWT_OS_LINUX __disable_warning_unused_static void sigalarm_handler(int signo) { int err; mwt_bigint_t on_counter; err = threadlock_tryenter(&mulwheeltimer.lock); if (err) { /** 多线程锁定失败 */ #if MWTIMER_PRINTF == 1 printf("[mwt]\033[33m lock error: %llu\033[0m\n", (unsigned long long) mulwheeltimer.counter); #endif return; } /** 当前激发的计数器 */ on_counter = mulwheeltimer.counter++; /** * 激发事件:此事件在锁定状态下调用用户提供的回调函数: * on_timer_event * * !! 因此不可以在on_timer_event中执行长时间的操作 !! */ mul_wheel_timer_fire_event(on_counter, mulwheeltimer.lpParameter); threadlock_leave(&mulwheeltimer.lock); #if MWTIMER_PRINTF == 1 printf(" * alarm: %llu\n", (unsigned long long) on_counter); #endif } #endif #ifdef MWT_OS_WINDOWS void __stdcall win_sigalrm_handler (PVOID lpParameter, BOOLEAN TimerOrWaitFired) { if (TimerOrWaitFired) { // TimerOrWaitFired: // If this parameter is TRUE, the wait timed out. // If this parameter is FALSE, the wait event has been signaled. // This parameter is always TRUE for timer callbacks. int err; mwt_bigint_t on_counter; // The wait timed out err = threadlock_tryenter(&mulwheeltimer.lock); if (err) { /** 多线程锁定失败 */ #if MWTIMER_PRINTF == 1 printf("[mwt]\033[33m lock error: %llu\033[0m\n", (unsigned long long) mulwheeltimer.counter); #endif return; } /** 当前激发的计数器 */ on_counter = mulwheeltimer.counter++; /** * 激发事件:此事件在锁定状态下调用用户提供的回调函数: * on_timer_event * * !! 因此不可以在on_timer_event中执行长时间的操作 !! */ mul_wheel_timer_fire_event(on_counter, lpParameter); threadlock_leave(&mulwheeltimer.lock); #if MWTIMER_PRINTF == 1 printf(" * alarm: %llu\n", (unsigned long long) on_counter); #endif printf(" * alarm: %lld\n", on_counter); } } #endif #if defined(__cplusplus) } #endif #endif /* MUL_WHEEL_TIMER_H_INCLUDED */