问题引入
- 如果要写一个完整的项目,一个可靠的定时器是不可或缺的,先实现一个简单的定时器,以后再慢慢完善。
介绍
- 基于 alarm() 发出 SIGALRM 信号驱动定时器运作
- 使用双向链表存储数据节点信息
代码
目录结构
double_llist.h
#ifndef DOUBLE_LLIST__
#define DOUBLE_LLIST__
typedef void d_llist_node_t;
typedef void d_llist_t;
int llist_init(d_llist_t **llist);
typedef int (*compare)(void *a, void *b);
int llist_insert(d_llist_t *llist, void *key, compare cmp);
d_llist_node_t *llist_pop_first(d_llist_t *llist);
d_llist_node_t *llist_pop_last(d_llist_t *llist);
d_llist_node_t *llist_head_look(d_llist_t *llist);
d_llist_node_t *llist_tail_look(d_llist_t *llist);
int llist_destroy(d_llist_t *llist);
typedef int (*traver)(void *node);
int llist_traver(d_llist_t *llist, traver tvr);
int llist_check(d_llist_t *llist, compare cmp);
d_llist_node_t *llist_find_node(d_llist_t *llist, void *key, compare cmp);
int llist_delete_node(d_llist_t *llist, void *key, compare cmp);
#endif
double_llist.c
#include <stdio.h>
#include <stdlib.h>
#include "./double_llist.h"
typedef struct llist_node_s{
void *key;
struct llist_node_s *prev;
struct llist_node_s *next;
}llist_node_t;
typedef struct llist_s{
llist_node_t *head;
llist_node_t *tail;
}llist_t;
int llist_init(void **llist){
llist_t *me = NULL;
me = (llist_t*)malloc(sizeof(*me));
if(me == NULL){
return -1;
}
me->head = NULL;
me->tail = NULL;
*llist = me;
return 0;
}
int llist_insert(d_llist_t *llist, void *key, compare cmp){
llist_t *me = llist;
llist_node_t *cur = me->head;
llist_node_t *node_ = NULL;
node_ = (llist_node_t*)malloc(sizeof(*node_));
if(node_ == NULL){
return -1;
}
node_->next = NULL;
node_->prev = NULL;
node_->key = key;
int res = 0;
while(cur != NULL){
res = cmp(key, cur->key);
if(res > 0){
cur = cur->next;
}else{
break;
}
}
if(cur == NULL){
node_->prev = me->tail;
node_->next = NULL;
if(me->tail != NULL){
me->tail->next = node_;
me->tail = node_;
}else{
me->tail = node_;
}
if(me->head == NULL){
me->head = node_;
}
}else if(cur == me->head){
node_->next = me->head;
node_->prev = NULL;
me->head->prev = node_;
me->head = node_;
}else{
node_->next = cur;
node_->prev = cur->prev;
cur->prev->next = node_;
cur->prev = node_;
}
return 0;
}
void *llist_pop_first(void *llist){
llist_t *me = llist;
llist_node_t *cur = me->head;
if(cur == NULL){
return NULL;
}else if(cur->next == NULL){
me->head = NULL;
me->tail = NULL;
}else{
me->head = cur->next;
me->head->prev = NULL;
}
void *ret = cur->key;
free(cur);
return ret;
}
void *llist_pop_last(void *llist){
llist_t *me = llist;
llist_node_t *cur = me->tail;
if(cur == NULL){
return NULL;
}else if(cur->prev == NULL){
me->head = NULL;
me->tail = NULL;
}else{
me->tail = cur->prev;
me->tail->next = NULL;
}
void *ret = cur->key;
free(cur);
return ret;
}
int llist_destroy(void *llist){
llist_t *me = llist;
llist_node_t *cur = me->head, *temp = NULL;
while(cur != NULL){
temp = cur->next;
free(cur->key);
free(cur);
cur = temp;
}
free(me);
llist = NULL;
return 0;
}
int llist_traver(void *llist, traver tvr){
llist_t *me = llist;
llist_node_t *cur = me->head;
while(cur != NULL){
tvr(cur->key);
cur = cur->next;
if(cur){
printf(" -> ");
}
}
printf("\n");
return 0;
}
int llist_check(void *llist, compare cmp){
llist_t *me = llist;
llist_node_t *cur = me->head;
if(cur != NULL && cur->next != NULL){
cur = cur->next;
}else{
return 0;
}
while(cur != NULL){
if(cmp(cur->key, cur->prev->key) < 0){
return -1;
}
cur = cur->next;
}
return 0;
}
d_llist_node_t *llist_head_look(d_llist_t *llist){
llist_t *me = llist;
if(me->head == NULL){
return NULL;
}
return me->head->key;
}
d_llist_node_t *llist_tail_look(d_llist_t *llist){
llist_t *me = llist;
if(me->tail == NULL){
return NULL;
}
return me->tail->key;
}
d_llist_node_t *llist_find_node(d_llist_t *llist, void *key, compare cmp){
llist_t *me = llist;
llist_node_t *cur = me->head;
int res = 0;
while(1){
if (cur == NULL){
return NULL;
}
res = cmp(key, cur->key);
if(res == 0){
return cur;
}
cur = cur->next;
}
return NULL;
}
int llist_delete_node(d_llist_t *llist, void *key, compare cmp){
llist_t *me = llist;
llist_node_t *cur = llist_find_node(llist, key, cmp);
if(cur == NULL){
return -1;
}
if(cur->prev == NULL && cur->next == NULL){
me->head = NULL;
me->tail = NULL;
}else if(cur->prev == NULL){
me->head = cur->next;
me->head->prev = NULL;
}else if(cur->next == NULL){
me->tail = cur->prev;
me->tail->next = NULL;
}else{
cur->next->prev = cur->prev;
cur->prev->next = cur->next;
}
#if 1
free(cur->key);
free(cur);
#endif
return 0;
}
timer.h
#ifndef _TIMER_H__
#define _TIMER_H__
typedef int (*callback)(void *);
typedef struct mytimer_st{
d_llist_t *llist;
time_t timeslot;
int start;
time_t pass;
}mytimer_t;
typedef struct timer_msg_st{
time_t expire;
int isloop;
callback cb;
void *arg;
}timer_msg_t;
int mytimer_init_timer(mytimer_t **timer, time_t timeslot);
int mytimer_start(mytimer_t *timer);
int mytimer_add_timer(mytimer_t *timer, time_t expire, int isloop, callback cb, void *arg);
typedef int (*compare_user)(void *a, void *b);
int mytimer_adjust_timer(mytimer_t *timer, void *key, time_t new_expir, int new_isloop, callback new_cb, void *new_age, compare_user cmp);
int mytimer_del_timer(mytimer_t *timer, void *key, compare_user cmp);
int mytimer_destroy_timer(mytimer_t *timer);
#endif
timer.c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <signal.h>
#include "../double_llist/double_llist.h"
#include "./timer.h"
static mytimer_t *for_signal_handler = NULL;
static int mycompare_expire(void *a, void *b){
timer_msg_t *x = a;
timer_msg_t *y = b;
return (x->expire) - (y->expire);
}
static int tick(void){
mytimer_t *me = for_signal_handler;
timer_msg_t *node = NULL;
me->pass += me->timeslot;
while(1){
node = llist_head_look(me->llist);
if(node == NULL){
break;
}
if(node->expire <= me->pass){
node->cb(node->arg);
node = llist_pop_first(me->llist);
if(node->isloop != 0){
node->expire = me->pass + node->isloop;
llist_insert(me->llist, node, mycompare_expire);
}else{
free(node);
}
}else{
break;
}
}
return 0;
}
static void signal_handler(int signo){
tick();
printf(".");
fflush(stdout);
alarm(for_signal_handler->timeslot);
return ;
}
int mytimer_init_timer(mytimer_t **timer, time_t timeslot){
mytimer_t *me = (mytimer_t*)malloc(sizeof(*me));
if(me == NULL){
return -1;
}
int ret;
ret = llist_init(&(me->llist));
if(ret){
return -1;
}
me->timeslot = timeslot;
me->start = 0;
me->pass = 0;
*timer = me;
for_signal_handler = me;
signal(SIGALRM, signal_handler);
return 0;
}
static int set_alarm(int sec){
alarm(sec);
return 0;
}
int mytimer_start(mytimer_t *timer){
mytimer_t *me = timer;
if(me->start == 0){
me->start = 1;
set_alarm(me->timeslot);
}
return 0;
}
int mytimer_add_timer(mytimer_t *timer, time_t expire, int isloop, callback cb, void *arg){
mytimer_t *me = timer;
timer_msg_t *willAdd = (timer_msg_t*)malloc(sizeof(*willAdd));
if(willAdd == NULL){
return -1;
}
willAdd->expire = expire + me->pass;
willAdd->cb = cb;
willAdd->arg = arg;
if(isloop == 1){
willAdd->isloop = expire;
}
int ret = llist_insert(me->llist, willAdd, mycompare_expire);
if(ret){
return -2;
}
return 0;
}
int mytimer_adjust_timer(mytimer_t *timer, void *key,
time_t new_expir, int new_isloop, callback new_cb, void *new_age, compare_user cmp){
mytimer_t *me = timer;
int res = 0;
res = llist_delete_node(me->llist, key, cmp);
if(res){
return -2;
}
timer_msg_t *node = (timer_msg_t*)malloc(sizeof(*node));
if(node == NULL){
return -1;
}
node->expire = new_expir + me->pass;
if(new_isloop == 1){
node->isloop = new_expir;
}
node->cb = new_cb;
node->arg = new_age;
return llist_insert(me->llist, node, mycompare_expire);
}
int mytimer_del_timer(mytimer_t *timer, void *key, compare_user cmp){
mytimer_t *me = timer;
int res = 0;
res = llist_delete_node(me->llist, key, cmp);
if(res){
return -1;
}
return 0;
}
int mytimer_destroy_timer(mytimer_t *timer){
mytimer_t *me = timer;
llist_destroy(me->llist);
free(me);
timer = NULL;
return 0;
}
test.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "../double_llist/double_llist.h"
#include "./timer.h"
int my_callback(void *arg){
char *data = arg;
printf("[%d]Hello World!\n", atoi(data));
return 0;
}
int my_compare(void *a, void *b){
timer_msg_t *B = b;
char *x = a;
char *y = B->arg;
int x_ = atoi(x);
int y_ = atoi(y);
return x_ - y_;
}
int mytraver(void *a){
timer_msg_t *msg = a;
printf("[%ld : %d]", msg->expire, atoi(msg->arg));
return 0;
}
int main(){
mytimer_t *timer = NULL;
int timeslot = 1;
int ret = 0;
ret = mytimer_init_timer(&timer, timeslot);
if(ret){
printf("init_timer() error!\n");
exit(1);
}
mytimer_start(timer);
mytimer_add_timer(timer, 2, 1, my_callback, "2");
mytimer_add_timer(timer, 3, 1, my_callback, "3");
mytimer_add_timer(timer, 5, 0, my_callback, "5");
mytimer_add_timer(timer, 10, 1, my_callback, "10");
mytimer_add_timer(timer, 30, 1, my_callback, "30");
llist_traver(timer->llist, mytraver);
int i = 0;
while(1){
if(i == 10){
mytimer_adjust_timer(timer, "2", 6, 1, my_callback, "6", my_compare);
}
pause();
i++;
}
mytimer_destroy_timer(timer);
exit(0);
}
总结
已实现功能
- 添加定时任务 / 循环任务
- 修改定时任务
- 删除定时任务
待实现功能
- 可以将数据结构再优化调整。