自己实现一个定时器

问题引入

  • 如果要写一个完整的项目,一个可靠的定时器是不可或缺的,先实现一个简单的定时器,以后再慢慢完善。

介绍

  • 基于 alarm() 发出 SIGALRM 信号驱动定时器运作
  • 使用双向链表存储数据节点信息

代码

目录结构

01

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);

// typedef int (*compare)(void *a, void *b);
int llist_check(d_llist_t *llist, compare cmp);

// new
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;
}

/*
    typedef int (*compare)(void *a, void *b);
    compare return value:
        1 : a > b
        -1 : a < b
        0 : a == b
*/
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{  // res < 0 || res == 0
            break;
        }

    }


    if(cur == NULL){
        // insert on tail
        // or head = tail = NULL, llist is 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){
        // insert on 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;
}

/*
typedef int (*traver)(void *node);
*/
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;
}


// new
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;
}

// 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){
    
    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);
}

// typedef int (*compare_user)(void *a, void *b);
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"


// typedef int (*callback)(void *);

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 *A = a;
    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);

    // mytimer_del_timer(timer, "2", my_compare);
    // mytimer_del_timer(timer, "10", my_compare);

    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);
}

总结

已实现功能

  1. 添加定时任务 / 循环任务
  2. 修改定时任务
  3. 删除定时任务

待实现功能

  1. 可以将数据结构再优化调整。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值