Compare commits
11 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
1e7ef0dd95 | |
|
|
01fe162ecf | |
|
|
6c8d47b9bb | |
|
|
f6286f4885 | |
|
|
a9ac521d91 | |
|
|
da4e0bf67e | |
|
|
07764643ac | |
|
|
78d1ac1ea6 | |
|
|
27d2717eab | |
|
|
f34faaf2de | |
|
|
0492ef5479 |
|
|
@ -0,0 +1,12 @@
|
||||||
|
CMakeLists.txt.user
|
||||||
|
CMakeCache.txt
|
||||||
|
CMakeFiles
|
||||||
|
CMakeScripts
|
||||||
|
Testing
|
||||||
|
Makefile
|
||||||
|
cmake_install.cmake
|
||||||
|
install_manifest.txt
|
||||||
|
compile_commands.json
|
||||||
|
CTestTestfile.cmake
|
||||||
|
|
||||||
|
build
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
cmake_minimum_required(VERSION 3.0)
|
||||||
|
project(timer)
|
||||||
|
|
||||||
|
set(CMAKE_BUILD_TYPE Release)
|
||||||
|
#set(CMAKE_C_FLAGS_RELEASE "$ENV${CFLAGS} -O3 -Wall")
|
||||||
|
|
||||||
|
include_directories(source)
|
||||||
|
|
||||||
|
add_subdirectory(source)
|
||||||
|
add_subdirectory(examples)
|
||||||
|
|
||||||
|
# uninstall target
|
||||||
|
if(NOT TARGET uninstall)
|
||||||
|
configure_file(
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
|
||||||
|
IMMEDIATE @ONLY)
|
||||||
|
|
||||||
|
add_custom_target(uninstall
|
||||||
|
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
include (CTest)
|
||||||
|
|
||||||
|
add_test(example examples/example)
|
||||||
|
|
||||||
32
README.md
32
README.md
|
|
@ -1,10 +1,10 @@
|
||||||
# MT_Timer(MT译为Multiple或Multi)
|
# MT_Timer(MT译为Multiple或Multi)
|
||||||
|
|
||||||
#### 介绍
|
#### 一、介绍
|
||||||
|
|
||||||
一个Linux下的超级简洁的定时器:*利用epoll机制和timerfd新特性实现的多重、多用、多个定时器实现*。只需要使用TIMER_CREATE()接口创建一个定时器实体,即**可向其添加成千上万个定时任务,定时任务可达到纳秒级别的精度,且可在同一时间点添加不同的定时任务!**。
|
一个Linux下的超级简洁的定时器:*利用epoll机制和timerfd新特性实现的多重、多用、多个定时任务实现*。只需要使用TIMER_CREATE()接口创建一个定时器实体,即**可向其添加成千上万个定时任务,定时任务可达到纳秒级别的精度,且可在同一时间点添加不同的定时任务!**。
|
||||||
|
|
||||||
#### 软件接口
|
#### 二、软件接口
|
||||||
|
|
||||||
整个定时器包含如下几类接口。
|
整个定时器包含如下几类接口。
|
||||||
|
|
||||||
|
|
@ -22,12 +22,12 @@ TIMER_DEINIT(name);
|
||||||
|
|
||||||
3. **添加和删除定时任务**:
|
3. **添加和删除定时任务**:
|
||||||
```
|
```
|
||||||
TIMER_ADD(name, itimespec, repeat, cb, data);
|
TIMER_ADD(name, itimespec, repeat, cb, data, rb);
|
||||||
TIMER_DEL(name, timerfd);
|
TIMER_DEL(name, timerfd);
|
||||||
```
|
```
|
||||||
|
|
||||||
TIMER_ADD()用于向定时器实例name中添加一个定时器,其参数描述如下:
|
TIMER_ADD()用于向定时器实例name中添加一个定时任务,其参数描述如下:
|
||||||
- ittimespec是定时器的定时时间和循环事件,其结构体类型如下:
|
- ittimespec是定时任务的定时时间和循环时间,其结构体类型如下:
|
||||||
```
|
```
|
||||||
struct timespec {
|
struct timespec {
|
||||||
time_t tv_sec; // seconds
|
time_t tv_sec; // seconds
|
||||||
|
|
@ -39,15 +39,15 @@ struct itimerspec {
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
其中it_value即是超时时间,若想定义周期定时任务,则设置it_interval成员;若不想定义周期定时器,则需设置it_interval成员都为0。因此,第一次超时和后面周期定时任务是可以使用不同时间的。
|
其中it_value即是超时时间(相对时间),若想定义周期定时任务,则设置it_interval成员;若不想定义周期定时任务,则需设置it_interval成员都为0。因此,第一次超时和后面周期定时任务是可以使用不同时间的。
|
||||||
|
|
||||||
- repeat是周期定时器的重复次数,若设置为**-1,代表永远重复;0,代表一次都不执行**;因此repeat应至少为1,或者使用-1;
|
- repeat是周期定时任务的重复次数,若设置为**-1,代表永远重复;0,代表一次都不执行**;因此repeat应至少为1,或者使用-1;
|
||||||
- cb为定时任务超时回调函数,其类型为:void (*timer_callback_t)(void *data);
|
- cb为定时任务超时回调函数,其类型为:void (*timer_callback_t)(void *data);
|
||||||
- data为定时任务回调函数的参数,为void *类型,用户可指定为自己定义的结构体;
|
- data为定时任务回调函数的参数,为void *类型,用户可指定为自己定义的结构体;
|
||||||
|
|
||||||
TIMER_ADD()添加定时任务成功返回新定时任务的文件描述符,失败返回 < 0。返回的文件描述符,可用于在TIMER_DEL()中删除定时器。
|
TIMER_ADD()添加定时任务成功返回新定时任务的文件描述符,失败返回 < 0。返回的文件描述符,可用于在TIMER_DEL()中删除定时任务。
|
||||||
|
|
||||||
4. **查询和清空定时器**
|
4. **查询和清空定时任务**
|
||||||
```
|
```
|
||||||
TIMER_COUNT(name);
|
TIMER_COUNT(name);
|
||||||
TIMER_CLEAR(name);
|
TIMER_CLEAR(name);
|
||||||
|
|
@ -55,9 +55,9 @@ TIMER_CLEAR(name);
|
||||||
|
|
||||||
TIMER_COUNT(name)用于查询定时器实例name中现存的定时任务个数;TIMER_CLEAR(name)用于清空定时器实例name中的所有定时任务。
|
TIMER_COUNT(name)用于查询定时器实例name中现存的定时任务个数;TIMER_CLEAR(name)用于清空定时器实例name中的所有定时任务。
|
||||||
|
|
||||||
#### 使用实例
|
#### 三、使用实例
|
||||||
|
|
||||||
下面是一个非常简单的使用示例:共创建了两个定时器,每个第一次超时都是3S,后面每隔1S超时一次;但第一个定时器频次为8,第二个定时器频次为3;当所有定时器都超时后,输入回车即可退出:
|
下面是一个非常简单的使用示例:共创建了两个定时任务,每个第一次超时都是3S,后面每隔1S超时一次;但第一个定时任务频次为8,第二个定时任务频次为3;当所有定时任务都超时后,输入回车即可退出:
|
||||||
```
|
```
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
@ -105,7 +105,11 @@ int main(void)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 参与贡献
|
#### 四、赞赏作者
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
#### 五、参与贡献
|
||||||
|
|
||||||
1. Fork 本仓库
|
1. Fork 本仓库
|
||||||
2. 新建 Feat_xxx 分支
|
2. 新建 Feat_xxx 分支
|
||||||
|
|
@ -113,7 +117,7 @@ int main(void)
|
||||||
4. 新建 Pull Request
|
4. 新建 Pull Request
|
||||||
|
|
||||||
|
|
||||||
#### 码云特技
|
#### 六、码云特技
|
||||||
|
|
||||||
1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
|
1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
|
||||||
2. 码云官方博客 [blog.gitee.com](https://blog.gitee.com)
|
2. 码云官方博客 [blog.gitee.com](https://blog.gitee.com)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
if(NOT EXISTS "@CMAKE_BINARY_DIR@/install_manifest.txt")
|
||||||
|
message(FATAL_ERROR "Cannot find install manifest: @CMAKE_BINARY_DIR@/install_manifest.txt")
|
||||||
|
endif(NOT EXISTS "@CMAKE_BINARY_DIR@/install_manifest.txt")
|
||||||
|
|
||||||
|
file(READ "@CMAKE_BINARY_DIR@/install_manifest.txt" files)
|
||||||
|
string(REGEX REPLACE "\n" ";" files "${files}")
|
||||||
|
foreach(file ${files})
|
||||||
|
message(STATUS "Uninstalling $ENV{DESTDIR}${file}")
|
||||||
|
if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
|
||||||
|
exec_program(
|
||||||
|
"@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
|
||||||
|
OUTPUT_VARIABLE rm_out
|
||||||
|
RETURN_VALUE rm_retval
|
||||||
|
)
|
||||||
|
if(NOT "${rm_retval}" STREQUAL 0)
|
||||||
|
message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}")
|
||||||
|
endif(NOT "${rm_retval}" STREQUAL 0)
|
||||||
|
else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
|
||||||
|
message(STATUS "File $ENV{DESTDIR}${file} does not exist.")
|
||||||
|
endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
|
||||||
|
endforeach(file)
|
||||||
|
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
cmake_minimum_required(VERSION 3.0)
|
||||||
|
project(examples)
|
||||||
|
|
||||||
|
link_libraries(pthread)
|
||||||
|
|
||||||
|
aux_source_directory(. SRCS)
|
||||||
|
|
||||||
|
add_executable(example ${SRCS})
|
||||||
|
target_link_libraries(example mttimer)
|
||||||
|
|
||||||
|
|
@ -51,8 +51,8 @@ int main(void)
|
||||||
itimespec.it_interval.tv_sec = 1;
|
itimespec.it_interval.tv_sec = 1;
|
||||||
itimespec.it_interval.tv_nsec = 0;
|
itimespec.it_interval.tv_nsec = 0;
|
||||||
|
|
||||||
timer = TIMER_ADD(test, &itimespec, 8, timeout_handle, NULL);
|
timer = TIMER_ADD(test, &itimespec, 8, timeout_handle, NULL, NULL);
|
||||||
TIMER_ADD(test, &itimespec, 3, timeout_handler, NULL);
|
TIMER_ADD(test, &itimespec, 3, timeout_handler, NULL, NULL);
|
||||||
printf("[%ld]:timer_add : %d\n", time(NULL), TIMER_COUNT(test));
|
printf("[%ld]:timer_add : %d\n", time(NULL), TIMER_COUNT(test));
|
||||||
|
|
||||||
sleep(4);//getchar();
|
sleep(4);//getchar();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
cmake_minimum_required(VERSION 3.0)
|
||||||
|
project(mttimer)
|
||||||
|
|
||||||
|
add_library(mttimer SHARED mt_timer.c)
|
||||||
|
set_target_properties(mttimer PROPERTIES VERSION 0.4 SOVERSION 1)
|
||||||
|
|
||||||
|
install (TARGETS mttimer DESTINATION lib)
|
||||||
|
install (FILES mt_timer.h DESTINATION include)
|
||||||
|
install (FILES uthash.h DESTINATION include)
|
||||||
|
|
@ -27,23 +27,54 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <sys/eventfd.h>
|
||||||
|
|
||||||
#include "mt_timer.h"
|
#include "mt_timer.h"
|
||||||
|
|
||||||
int timer_init(MT_TIMER_OBJECT *object, void *(*thread_handler)(void *arg), int max_num)
|
int timer_init(MT_TIMER_OBJECT *object, void *(*thread_handler)(void *arg), int max_num)
|
||||||
{
|
{
|
||||||
|
struct epoll_event event;
|
||||||
|
assert(NULL != object);
|
||||||
|
if(true == object->timer_active_flag)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
object->timer_event_fd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
|
||||||
|
if(-1 == object->timer_event_fd)
|
||||||
|
{
|
||||||
|
MT_TIMER_PRINT_INL("MT-Timer error: eventfd() failed, %s!\n", strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
object->timer_max = max_num;
|
object->timer_max = max_num;
|
||||||
object->timer_active_flag = true;
|
object->timer_active_flag = true;
|
||||||
object->timer_epoll_fd = epoll_create(max_num);
|
object->timer_epoll_fd = epoll_create(max_num);
|
||||||
if(object->timer_epoll_fd < 0)
|
if(object->timer_epoll_fd < 0)
|
||||||
{
|
{
|
||||||
MT_TIMER_PRINT_INL("MT-Timer error: epoll_create failed %s.\n", strerror(errno));
|
MT_TIMER_PRINT_INL("MT-Timer error: epoll_create failed %s.\n", strerror(errno));
|
||||||
|
close(object->timer_event_fd);
|
||||||
|
object->timer_event_fd = -1;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
event.data.ptr = NULL;
|
||||||
|
event.events = EPOLLIN | EPOLLET;
|
||||||
|
if(epoll_ctl(object->timer_epoll_fd, EPOLL_CTL_ADD, object->timer_event_fd, &event) < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "epoll: epoll_ctl ADD failed, %s\n", strerror(errno));
|
||||||
|
close(object->timer_epoll_fd);
|
||||||
|
close(object->timer_event_fd);
|
||||||
|
object->timer_epoll_fd = -1;
|
||||||
|
object->timer_event_fd = -1;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(pthread_create(&object->timer_thread_id, NULL, thread_handler, NULL) != 0)
|
if(pthread_create(&object->timer_thread_id, NULL, thread_handler, NULL) != 0)
|
||||||
{
|
{
|
||||||
MT_TIMER_PRINT_INL("MT-Timer error: pthread_create failed %s.\n", strerror(errno));
|
MT_TIMER_PRINT_INL("MT-Timer error: pthread_create failed %s.\n", strerror(errno));
|
||||||
|
close(object->timer_epoll_fd);
|
||||||
|
close(object->timer_event_fd);
|
||||||
|
object->timer_epoll_fd = -1;
|
||||||
|
object->timer_event_fd = -1;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -52,26 +83,28 @@ int timer_init(MT_TIMER_OBJECT *object, void *(*thread_handler)(void *arg), int
|
||||||
|
|
||||||
void timer_deinit(MT_TIMER_OBJECT *object)
|
void timer_deinit(MT_TIMER_OBJECT *object)
|
||||||
{
|
{
|
||||||
struct itimerspec itimespec;
|
uint64_t quit = 0x51;
|
||||||
|
assert(NULL != object);
|
||||||
|
if(false == object->timer_active_flag)
|
||||||
|
return ;
|
||||||
object->timer_active_flag = false;
|
object->timer_active_flag = false;
|
||||||
|
usleep(100);
|
||||||
itimespec.it_value.tv_sec = 0;
|
write(object->timer_event_fd, &quit, sizeof(uint64_t)); /* wakeup thread */
|
||||||
itimespec.it_value.tv_nsec = 50;
|
|
||||||
itimespec.it_interval.tv_sec = 0;
|
|
||||||
itimespec.it_interval.tv_nsec = 0;
|
|
||||||
|
|
||||||
timer_add(object, &itimespec, 0, NULL, NULL);
|
|
||||||
pthread_join(object->timer_thread_id, NULL);
|
pthread_join(object->timer_thread_id, NULL);
|
||||||
timer_clear(object);
|
timer_clear(object);
|
||||||
|
close(object->timer_epoll_fd);
|
||||||
|
close(object->timer_event_fd);
|
||||||
|
object->timer_epoll_fd = -1;
|
||||||
|
object->timer_event_fd = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int timer_add(MT_TIMER_OBJECT *object, struct itimerspec *itimespec,
|
int timer_add(MT_TIMER_OBJECT *object, struct itimerspec *itimespec,
|
||||||
int repeat, timer_callback_t cb, void *data)
|
int repeat, timer_callback_t cb, void *data, timer_release_t rb)
|
||||||
{
|
{
|
||||||
|
uint64_t quit = 0x51;
|
||||||
struct epoll_event event;
|
struct epoll_event event;
|
||||||
MT_TIMER_NODE *handler = NULL;
|
MT_TIMER_NODE *handler = NULL;
|
||||||
|
assert(NULL != object);
|
||||||
handler = (MT_TIMER_NODE *)malloc(sizeof(MT_TIMER_NODE));
|
handler = (MT_TIMER_NODE *)malloc(sizeof(MT_TIMER_NODE));
|
||||||
if(NULL == handler)
|
if(NULL == handler)
|
||||||
{
|
{
|
||||||
|
|
@ -80,6 +113,7 @@ int timer_add(MT_TIMER_OBJECT *object, struct itimerspec *itimespec,
|
||||||
}
|
}
|
||||||
|
|
||||||
handler->timer_cb = cb;
|
handler->timer_cb = cb;
|
||||||
|
handler->release_cb = rb;
|
||||||
handler->timer_cnt = repeat;
|
handler->timer_cnt = repeat;
|
||||||
handler->timer_data = data;
|
handler->timer_data = data;
|
||||||
handler->timer_fd = timerfd_create(CLOCK_REALTIME, TFD_CLOEXEC|TFD_NONBLOCK);
|
handler->timer_fd = timerfd_create(CLOCK_REALTIME, TFD_CLOEXEC|TFD_NONBLOCK);
|
||||||
|
|
@ -106,7 +140,7 @@ int timer_add(MT_TIMER_OBJECT *object, struct itimerspec *itimespec,
|
||||||
free(handler);
|
free(handler);
|
||||||
return -4;
|
return -4;
|
||||||
}
|
}
|
||||||
|
write(object->timer_event_fd, &quit, sizeof(uint64_t)); /* wakeup thread */
|
||||||
pthread_rwlock_wrlock(&object->timer_rwlock);
|
pthread_rwlock_wrlock(&object->timer_rwlock);
|
||||||
HASH_ADD_INT(object->timer_head, timer_fd, handler);
|
HASH_ADD_INT(object->timer_head, timer_fd, handler);
|
||||||
pthread_rwlock_unlock(&object->timer_rwlock);
|
pthread_rwlock_unlock(&object->timer_rwlock);
|
||||||
|
|
@ -118,7 +152,7 @@ int timer_del(MT_TIMER_OBJECT *object, int timerfd)
|
||||||
{
|
{
|
||||||
struct epoll_event event;
|
struct epoll_event event;
|
||||||
MT_TIMER_NODE *handler = NULL;
|
MT_TIMER_NODE *handler = NULL;
|
||||||
|
assert(NULL != object);
|
||||||
pthread_rwlock_rdlock(&object->timer_rwlock);
|
pthread_rwlock_rdlock(&object->timer_rwlock);
|
||||||
HASH_FIND_INT(object->timer_head, &timerfd, handler);
|
HASH_FIND_INT(object->timer_head, &timerfd, handler);
|
||||||
pthread_rwlock_unlock(&object->timer_rwlock);
|
pthread_rwlock_unlock(&object->timer_rwlock);
|
||||||
|
|
@ -137,6 +171,8 @@ int timer_del(MT_TIMER_OBJECT *object, int timerfd)
|
||||||
HASH_DEL(object->timer_head, handler);
|
HASH_DEL(object->timer_head, handler);
|
||||||
pthread_rwlock_unlock(&object->timer_rwlock);
|
pthread_rwlock_unlock(&object->timer_rwlock);
|
||||||
close(handler->timer_fd);
|
close(handler->timer_fd);
|
||||||
|
if(handler->release_cb)
|
||||||
|
handler->release_cb(handler->timer_data);
|
||||||
free(handler);
|
free(handler);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -144,6 +180,7 @@ int timer_del(MT_TIMER_OBJECT *object, int timerfd)
|
||||||
|
|
||||||
int timer_count(MT_TIMER_OBJECT *object)
|
int timer_count(MT_TIMER_OBJECT *object)
|
||||||
{
|
{
|
||||||
|
assert(NULL != object);
|
||||||
return HASH_COUNT(object->timer_head);
|
return HASH_COUNT(object->timer_head);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -151,7 +188,7 @@ int timer_clear(MT_TIMER_OBJECT *object)
|
||||||
{
|
{
|
||||||
struct epoll_event event;
|
struct epoll_event event;
|
||||||
MT_TIMER_NODE *handler = NULL;
|
MT_TIMER_NODE *handler = NULL;
|
||||||
|
assert(NULL != object);
|
||||||
event.events = EPOLLIN | EPOLLET;
|
event.events = EPOLLIN | EPOLLET;
|
||||||
for(handler = object->timer_head; handler != NULL; handler = handler->hh.next)
|
for(handler = object->timer_head; handler != NULL; handler = handler->hh.next)
|
||||||
{
|
{
|
||||||
|
|
@ -165,6 +202,8 @@ int timer_clear(MT_TIMER_OBJECT *object)
|
||||||
HASH_DEL(object->timer_head, handler);
|
HASH_DEL(object->timer_head, handler);
|
||||||
pthread_rwlock_unlock(&object->timer_rwlock);
|
pthread_rwlock_unlock(&object->timer_rwlock);
|
||||||
close(handler->timer_fd);
|
close(handler->timer_fd);
|
||||||
|
if(handler->release_cb)
|
||||||
|
handler->release_cb(handler->timer_data);
|
||||||
free(handler);
|
free(handler);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,7 @@ typedef enum{false, true} bool;
|
||||||
#define bool bool
|
#define bool bool
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef void (*timer_release_t)(void *data);
|
||||||
typedef void (*timer_callback_t)(void *data);
|
typedef void (*timer_callback_t)(void *data);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
@ -78,11 +79,13 @@ typedef struct {
|
||||||
void *timer_data;
|
void *timer_data;
|
||||||
UT_hash_handle hh;
|
UT_hash_handle hh;
|
||||||
timer_callback_t timer_cb;
|
timer_callback_t timer_cb;
|
||||||
|
timer_release_t release_cb;
|
||||||
}MT_TIMER_NODE; /* MT mean multiple */
|
}MT_TIMER_NODE; /* MT mean multiple */
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int timer_max;
|
int timer_max;
|
||||||
int timer_epoll_fd;
|
int timer_epoll_fd;
|
||||||
|
int timer_event_fd;
|
||||||
bool timer_active_flag;
|
bool timer_active_flag;
|
||||||
MT_TIMER_NODE *timer_head;
|
MT_TIMER_NODE *timer_head;
|
||||||
pthread_t timer_thread_id;
|
pthread_t timer_thread_id;
|
||||||
|
|
@ -93,6 +96,7 @@ typedef struct {
|
||||||
static void *mt_timer_thread_##name(void *arg) \
|
static void *mt_timer_thread_##name(void *arg) \
|
||||||
{ \
|
{ \
|
||||||
int nfds, i; \
|
int nfds, i; \
|
||||||
|
uint64_t u64; \
|
||||||
char buf[128]; \
|
char buf[128]; \
|
||||||
struct epoll_event event; \
|
struct epoll_event event; \
|
||||||
MT_TIMER_NODE *timer_node = NULL; \
|
MT_TIMER_NODE *timer_node = NULL; \
|
||||||
|
|
@ -109,7 +113,10 @@ typedef struct {
|
||||||
{ \
|
{ \
|
||||||
timer_node = (MT_TIMER_NODE *)events[i].data.ptr; \
|
timer_node = (MT_TIMER_NODE *)events[i].data.ptr; \
|
||||||
if(NULL == timer_node) \
|
if(NULL == timer_node) \
|
||||||
|
{ \
|
||||||
|
read(mt_timer_##name.timer_event_fd, &u64, sizeof(uint64_t)); \
|
||||||
continue; \
|
continue; \
|
||||||
|
} \
|
||||||
while(read(timer_node->timer_fd, buf, sizeof(buf)) > 0); \
|
while(read(timer_node->timer_fd, buf, sizeof(buf)) > 0); \
|
||||||
if(NULL == timer_node->timer_cb) \
|
if(NULL == timer_node->timer_cb) \
|
||||||
continue; \
|
continue; \
|
||||||
|
|
@ -130,6 +137,8 @@ typedef struct {
|
||||||
HASH_DEL(mt_timer_##name.timer_head, timer_node); \
|
HASH_DEL(mt_timer_##name.timer_head, timer_node); \
|
||||||
pthread_rwlock_unlock(&mt_timer_##name.timer_rwlock); \
|
pthread_rwlock_unlock(&mt_timer_##name.timer_rwlock); \
|
||||||
close(timer_node->timer_fd); \
|
close(timer_node->timer_fd); \
|
||||||
|
if(timer_node->release_cb) \
|
||||||
|
timer_node->release_cb(timer_node->timer_data); \
|
||||||
free(timer_node); \
|
free(timer_node); \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
|
|
@ -142,14 +151,14 @@ typedef struct {
|
||||||
extern int timer_init(MT_TIMER_OBJECT *object, void *(*thread_handler)(void *arg), int max_num);
|
extern int timer_init(MT_TIMER_OBJECT *object, void *(*thread_handler)(void *arg), int max_num);
|
||||||
extern void timer_deinit(MT_TIMER_OBJECT *object);
|
extern void timer_deinit(MT_TIMER_OBJECT *object);
|
||||||
extern int timer_add(MT_TIMER_OBJECT *object, struct itimerspec *itimespec,
|
extern int timer_add(MT_TIMER_OBJECT *object, struct itimerspec *itimespec,
|
||||||
int repeat, timer_callback_t cb, void *data);
|
int repeat, timer_callback_t cb, void *data, timer_release_t rb);
|
||||||
extern int timer_del(MT_TIMER_OBJECT *object, int timerfd);
|
extern int timer_del(MT_TIMER_OBJECT *object, int timerfd);
|
||||||
extern int timer_count(MT_TIMER_OBJECT *object);
|
extern int timer_count(MT_TIMER_OBJECT *object);
|
||||||
extern int timer_clear(MT_TIMER_OBJECT *object);
|
extern int timer_clear(MT_TIMER_OBJECT *object);
|
||||||
|
|
||||||
/************************** API Interface **************************/
|
/************************** API Interface **************************/
|
||||||
#define TIMER_CREATE(name) \
|
#define TIMER_CREATE(name) \
|
||||||
MT_TIMER_OBJECT mt_timer_##name = {0, -1, false, NULL, 0, PTHREAD_RWLOCK_INITIALIZER}; \
|
MT_TIMER_OBJECT mt_timer_##name = {0, -1, -1, false, NULL, 0, PTHREAD_RWLOCK_INITIALIZER}; \
|
||||||
TIMER_THREAD_CREATE(name)
|
TIMER_THREAD_CREATE(name)
|
||||||
#define TIMER_DECLEAR(name) \
|
#define TIMER_DECLEAR(name) \
|
||||||
extern MT_TIMER_OBJECT mt_timer_##name
|
extern MT_TIMER_OBJECT mt_timer_##name
|
||||||
|
|
@ -157,8 +166,8 @@ extern int timer_clear(MT_TIMER_OBJECT *object);
|
||||||
timer_init(&mt_timer_##name, mt_timer_thread_##name, max)
|
timer_init(&mt_timer_##name, mt_timer_thread_##name, max)
|
||||||
#define TIMER_DEINIT(name) \
|
#define TIMER_DEINIT(name) \
|
||||||
timer_deinit(&mt_timer_##name)
|
timer_deinit(&mt_timer_##name)
|
||||||
#define TIMER_ADD(name, itimespec, repeat, cb, data) \
|
#define TIMER_ADD(name, itimespec, repeat, cb, data, rb) \
|
||||||
timer_add(&mt_timer_##name, itimespec, repeat, cb, data)
|
timer_add(&mt_timer_##name, itimespec, repeat, cb, data, rb)
|
||||||
#define TIMER_DEL(name, timerfd) \
|
#define TIMER_DEL(name, timerfd) \
|
||||||
timer_del(&mt_timer_##name, timerfd)
|
timer_del(&mt_timer_##name, timerfd)
|
||||||
#define TIMER_COUNT(name) timer_count(&mt_timer_##name)
|
#define TIMER_COUNT(name) timer_count(&mt_timer_##name)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue