c文件=====================================================
关于list_head请看另一篇文章http://blog.csdn.net/lvhongya/article/details/6609565
/*
* This file provides an interface of timers with signal and list
*/
#include "pub_time.h"
#define MAX_TIMER_NUM 1000 /**< max timer number */
#define TIMER_START 10 /**< timer start(m second)*/
#define TIMER_TICK 10 /**< timer tick(m second) */
#define INVALID_TIMER_ID (-1) /**< invalid timer ID */
static pub_timer_list_t timer_list;
static void signal_func(int signo);
/**
* Create a timer list.
*
* @param count The maximum number of timer entries to be supported
* initially.
*
* @return 0 means ok, the other means fail.
*/
int pub_timer_init(int count)
{
int ret = 0;
if(count <=0 || count > MAX_TIMER_NUM) {
printf("the timer max number MUST less than %d.\n", MAX_TIMER_NUM);
return -1;
}
memset(&timer_list, 0, sizeof(pub_timer_list_t));
INIT_LIST_HEAD(&timer_list.header);
timer_list.max_num = count;
/* Register our internal signal handler and store old signal handler */
if ((timer_list.old_sigfunc = signal(SIGALRM, signal_func)) == SIG_ERR) {
return -1;
}
timer_list.new_sigfunc = signal_func;
/* Setting our interval timer for driver our mutil-timer and store old timer value */
timer_list.value.it_value.tv_sec = 0;
timer_list.value.it_value.tv_usec = TIMER_START*1000;
timer_list.value.it_interval.tv_sec = 0;
timer_list.value.it_interval.tv_usec = TIMER_TICK*1000;
ret = setitimer(ITIMER_REAL, &timer_list.value, &timer_list.ovalue);
return ret;
}
/**
* Destroy the timer list.
*
* @return 0 means ok, the other means fail.
*/
int pub_timer_destroy(void)
{
pub_timer_t *node = NULL;
if ((signal(SIGALRM, timer_list.old_sigfunc)) == SIG_ERR) {
return -1;
}
if((setitimer(ITIMER_REAL, &timer_list.ovalue, &timer_list.value)) < 0) {
return -1;
}
while (!list_empty(&timer_list.header))
{/* Delete. */
node = list_first_entry(&timer_list.header, pub_timer_t , list);
list_del(timer_list.header.next);
/* Free node */
printf("Remove id %d\n", node->id);
free(node->user_data);
free(node);
}
memset(&timer_list, 0, sizeof(pub_timer_list_t));
return 0;
}
//获得绝对超时时间
void time_to_absolute(struct timeval *time,struct timeval *interval)
{
struct timeval time_now;
gettimeofday(&time_now,NULL);
if(time_now.tv_usec+interval->tv_usec>=1000000)
{
time->tv_sec=time_now.tv_sec+interval->tv_sec+1;
time->tv_usec=time_now.tv_usec+interval->tv_usec-1000000;
}
else
{
time->tv_sec=time_now.tv_sec+interval->tv_sec;
time->tv_usec=time_now.tv_usec+interval->tv_usec;
}
}
//将新的计时器插入队列
int static pub_timer_insert(pub_timer_t *timer)
{
if(list_empty(&timer_list.header))
{
list_add(&timer->list, &timer_list.header);
}
else
{
pub_timer_t *timer_tmp;
struct list_head *pos;
list_for_each(pos, &timer_list.header)
{
timer_tmp=list_entry(pos, pub_timer_t, list);
if(timercmp(&timer->overtime,&timer_tmp->overtime,<))
{
list_add(pos,&timer->list);
return timer->id;
}
}
list_add_tail(&timer->list, &timer_list.header);
}
return timer->id;
}
/**
* Add a timer to timer list.
*
* @param interval The timer interval(second).
* @param cb When cb!= NULL and timer expiry, call it.
* @param user_data Callback's param.
* @param len The length of the user_data.
*
* @return The timer ID, if == INVALID_TIMER_ID, add timer fail.
*/
timer_id pub_timer_add(struct timeval *interval, timer_expiry *cb, void *user_data, int len)
{
pub_timer_t *node = NULL;
if (cb == NULL || interval <= 0)
{
return INVALID_TIMER_ID;
}
if(timer_list.num < timer_list.max_num)
{
timer_list.num++;
}
else
{
return INVALID_TIMER_ID;
}
if((node = malloc(sizeof(pub_timer_t))) == NULL)
{
return INVALID_TIMER_ID;
}
if(user_data != NULL || len != 0)
{
node->user_data = malloc(len);
memcpy(node->user_data, user_data, len);
node->len = len;
}
node->cb = cb;
memcpy(&node->interval,interval,sizeof(struct timeval));
time_to_absolute(&node->overtime,interval);
node->id = timer_list.num;
return pub_timer_insert(node);
}
/**
* Delete a timer from timer list.
*
* @param id The timer ID.
*
* @return 0 means ok, the other fail.
*/
int pub_timer_del(timer_id id)
{
if (id <0 || id > timer_list.max_num) {
return -1;
}
pub_timer_t *timer_tmp;
struct list_head *pos;
list_for_each(pos, &timer_list.header)
{
timer_tmp=list_entry(pos, pub_timer_t, list);
if(timer_tmp->id==id)
{
printf("Total timer num %d/timer id %d.\n", timer_list.num, id);
list_del(pos);
timer_list.num--;
free(timer_tmp->user_data);
free(timer_tmp);
return 0;
}
}
/* Can't find the timer */
return -1;
}
/* Tick Bookkeeping */
static void signal_func(int signo)
{
pub_timer_t *timer_tmp;
struct list_head *pos;
struct timeval time_now;
gettimeofday(&time_now,NULL);
//printf("here\n");
list_for_each(pos, &timer_list.header)
{
timer_tmp=list_entry(pos, pub_timer_t, list);
if(timercmp(&timer_tmp->overtime, &time_now, >))
{
break;
}
time_to_absolute(&timer_tmp->overtime, &timer_tmp->interval);
timer_tmp->cb(timer_tmp->id, timer_tmp->user_data, timer_tmp->len);
list_del(pos);
pub_timer_insert(timer_tmp);
}
}
=====h文件========================================================
#ifndef _PUB_TIME_H
#define _PUB_TIME_H
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <time.h>
#include <sys/time.h>
#include "pub_list.h"
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
typedef int timer_id;
/**
* The type of callback function to be called by timer scheduler when a timer
* has expired.
*
* @param id The timer id.
* @param user_data The user data.
* $param len The length of user data.
*/
typedef int timer_expiry(timer_id id, void *user_data, int len);
/**
* The type of the timer
*/
typedef struct _put_timer
{
struct list_head list; /**< list list */
timer_id id; /**< timer id */
struct timeval interval;/**< timer interval*/
struct timeval overtime; /**< 0 -> interval */
timer_expiry *cb; /**< call if expiry */
void *user_data; /**< callback arg */
int len; /**< user_data length */
}pub_timer_t;
/**
* The timer list
*/
typedef struct _timer_list {
struct list_head header; /**< list header */
int num; /**< timer entry number */
int max_num; /**< max entry number */
void (*old_sigfunc)(int); /**< save previous signal handler */
void (*new_sigfunc)(int); /**< our signal handler */
struct itimerval ovalue; /**< old timer value */
struct itimerval value; /**< our internal timer value */
}pub_timer_list_t;
#ifndef timercmp
#define timercmp(tvp, uvp, cmp) \
((tvp)->tv_sec cmp (uvp)->tv_sec || \
(tvp)->tv_sec == (uvp)->tv_sec && (tvp)->tv_usec cmp (uvp)->tv_usec)
#endif
int pub_timer_init(int count);
int pub_timer_destroy(void);
timer_id pub_timer_add(struct timeval *interval, timer_expiry *cb, void *user_data, int len);
int pub_timer_del(timer_id id);
#endif /* _PUB_TIME_H */