/***********************************************************************
* 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
* multi wheel timer for linux
*
* refer:
* javascript:void(0)
* 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_INCLUDED
#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 MAX_TIMER_CNT 10
#define MUL_TIMER_RESET_SEC 10
#define TIMER_UNIT 60
#define MAX_FUNC_ARG_LEN 100
#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_info[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) {
continue;
}
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 */