one of the implementations of Linux multi-timer
Time management is the main task of computer system. In time management, often use the timer to deal with things: such as the use of the TCP Protocol Timer management packet timeout, video display in the use of timer to display video frames, the use of the timer in the Web services to manage user timeout, scheduling tasks in time to inspire tasks. Windows provides a timer interface such as SetTimer and timeSetEvent, while Linux provides interfaces such as Setitimer. The interfaces of these functions are very similar, in general the user provides callback functions and timeout time to register a timer event with the OS, and when the OS is timed out, the user-supplied callback function is invoked to accomplish what the user wants to do. Windows interfaces support a single process with multiple timers, while Linux only allows a single process to have a timer, so in a single process under Linux to use more than one timer, you need to maintain management. In addition, the OS provides the timer management algorithm in the large-scale timer management may not be satisfactory, this time the user to optimize the management algorithm, this article in this regard provides a bit of material. first implement a simple multiple timer
This implementation allows the user to use multiple custom timers, and each custom timer will be triggered periodically until it is deleted. The main ideas to realize are:
I first use Setitimer to register a timed event for a basic time unit (such as 1s) when initializing multiple timers (mul_wheel_timer_init);
II Users need to register (mul_wheel_timer_set) custom timer, in the mul_wheel_timer_t structure to record the timer callback function and timing cycle parameters;
III when the basic unit of time expires (such as when the SIGALRM signal arrives), traverse the entire mul_wheel_timer, and if there is a custom timer timeout, execute the corresponding callback function and place the custom timer time-out to the original value Otherwise, the timeout time of the custom timer is reduced accordingly to a basic time unit;
Here is the C code (MUL_WHEEL_TIMER.H) under Linux:
/*********************************************************************** * Copyright (c) 2018 Pepstack, pepstack.com * This software are provided ' as-is ', without any express or implied * warranty.
In no event would the authors be held liable to any damages * arising from the ' use of ' this software. * Permission is granted to anyone to the use of this software for all purpose, * including commercial, and to alter It and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must is not misrepresented; You are must not * claim this you wrote the original software. If you use this software * to a product, an acknowledgment in the product documentation would being * appreciated but is
Not required. * * 2.
Altered source versions must is plainly marked as such, and must not * is misrepresented as being the original. * * 3.
This notice may is removed or altered from any source distribution. ************************************//** * Mul_wheel_timer.h * Multi wheel timer for Linux * Refer: * http://b log.csdn.net/zhangxinrun/article/details/5914191 * Https://linux.die.net/man/2/setitimer * * Author:master@pepstack . com * * create:2018-02-03 * update:2018-02-03/#ifndef mul_wheel_timer_h_included #define MUL_WHEEL_TIMER_H_INCLU DED #if defined (__cplusplus) extern "C" {#endif #include <assert.h> #include <stdio.h> #include <string. h> #include <memory.h> #include <malloc.h> #include <time.h> #include <sys/time.h> #define M AX_TIMER_CNT #define MUL_TIMER_RESET_SEC #define TIMER_UNIT #define Max_func_arg_len
#define INVALID_TIMER_HANDLE ( -1) typedef int timer_handle_t; typedef struct MUL_WHEEL_TIMER_T {struct _timer_info {int state;
/* ON (1) or off (0) */int interval; int elapse; /* 0~interval */INT (* Timer_func) (void *arg, int arglen);
Char tmfn_arg[255];
int Tmfn_arglen;
} timer_info[max_timer_cnt];
void (* old_sigfunc) (int);
void (* new_sigfunc) (int);
struct Itimerval value, oldvalue;
} * mul_wheel_timer_t;
__ATTRIBUTE__ ((used)) static struct mul_wheel_timer_t mul_wheel_timer;
__ATTRIBUTE__ ((used)) static void Sigfunc_ontimer (int signo) {int i;
for (i = 0; i < max_timer_cnt i++) {if (mul_wheel_timer.timer_info[i].state = 0) {continue;
} mul_wheel_timer.timer_info[i].elapse++; if (Mul_wheel_timer.timer_info[i].elapse = = mul_wheel_timer.timer_info[i].interval) {mul_wheel_timer.timer_in
Fo[i].elapse = 0; Mul_wheel_timer.timer_info[i].timer_func (Mul_wheel_timer.timer_info[i].tmfn_arg, mul_wheel_timer.timer_info[i).
Tmfn_arglen);
}}/** * success, return 0; * Failed, Return-1/__attribute__ ((used)) static int mul_wheel_timer_init (void) {int ret;
Bzero (&mul_wheel_timer, sizeof (struct mul_wheel_timer_t));
if ((Mul_wheel_timer.old_sigfunc = Signal (SIGALRM, sigfunc_ontimer)) = = Sig_err) {return (-1);
} Mul_wheel_timer.new_sigfunc = Sigfunc_ontimer;
Mul_wheel_timer.value.it_value.tv_sec = mul_timer_reset_sec;
mul_wheel_timer.value.it_value.tv_usec = 0;
Mul_wheel_timer.value.it_interval.tv_sec = Timer_unit;
mul_wheel_timer.value.it_interval.tv_usec = 0;
ret = Setitimer (Itimer_real, &mul_wheel_timer.value, &mul_wheel_timer.oldvalue);
return (ret);
/** * success, return 0;
* Failed, Return-1 * * __attribute__ ((used)) static int Mul_wheel_timer_destroy (void) {int ret;
if ((Signal (SIGALRM, mul_wheel_timer.old_sigfunc)) = = Sig_err) {return (-1);
ret = Setitimer (Itimer_real, &mul_wheel_timer.oldvalue, &mul_wheel_timer.value);
if (Ret < 0) {return (-1); } bzero (&mul_wheel_timer, sizeof (StruCT mul_wheel_timer_t));
return (0);
/** * success, return 0; * Failed, Return-1 * * __attribute__ ((used)) static int Mul_wheel_timer_del (timer_handle_t handle) {if (Handle < 0 | |
Handle >= max_timer_cnt) {return (-1);
} bzero (&mul_wheel_timer.timer_info[handle], sizeof (mul_wheel_timer.timer_info[handle));
return (0);
}/** * Success, return timer handle (0 based); * Failed, Return-1 * * __attribute__ ((used)) static timer_handle_t mul_wheel_timer_set (int interval, int (* timer_func)
(void *arg, int arglen), void *arg, int arglen) {timer_handle_t i;
if (! Timer_func | | interval <= 0) {return invalid_timer_handle; for (i = 0; i < max_timer_cnt i++) {if (Mul_wheel_timer.timer_info[i].state = 1) {Contin
Ue
} bzero (&mul_wheel_timer.timer_info[i], sizeof (mul_wheel_timer.timer_info[i));
Mul_wheel_timer.timer_info[i].timer_func = Timer_func; if (ARG) {if (Arglen > Max_func_arg_len) {return invalid_timer_handle;
} memcpy (Mul_wheel_timer.timer_info[i].tmfn_arg, ARG, Arglen);
Mul_wheel_timer.timer_info[i].tmfn_arglen = Arglen;
} mul_wheel_timer.timer_info[i].interval = interval;
Mul_wheel_timer.timer_info[i].elapse = 0; Mul_wheel_timer.timer_info[i].state = 1;
* * Timer is on/break;
} if (I >= max_timer_cnt) {/* full */return invalid_timer_handle;
}/* Success return Timer index */return (i);
#if defined (__cplusplus)} #endif #endif/* mul_wheel_timer_h_included * *
This timer has obvious flaws: new timer, traversal timer and delete timer (find which timer timeout) when the time complexity is O (n) (n is the number of timers); The applicable environment is a single-threaded environment, and if you want to use it for multiple threads, you need to add synchronization operations.
There are some minor bugs in the program, such as a timer with a new timeout of 0 that is not properly handled.
Here's how it's going to be improved!
reference article [1]: http://blog.csdn.net/zhangxinrun/article/details/5914191