博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Linux环境下基于链表的定时器的C语言实现
阅读量:2029 次
发布时间:2019-04-28

本文共 12182 字,大约阅读时间需要 40 分钟。

#include "crtl/crtl_alloc.h"#include "crtl/crtl_time.h"#include "crtl/crtl_timer.h"#include "crtl/crtl_types.h"#include "crtl/crtl_log.h"#include "crtl/crtl_assert.h"#include "crtl/crtl_task.h"#include "crtl/bits/crtl_lock_rwlock.h"#include "crtl/easy/byteswap.h"/* 定时器列表的读写锁 */static crtl_lock_rw_t _unused __crtl_timers_list_rwlock = CRTL_LOCK_RWLOCK_INITIALIZER;#define __crtl_timers_list_rdlock crtl_rwlock_rdlock(&__crtl_timers_list_rwlock, 0,0,0,0)#define __crtl_timers_list_wrlock crtl_rwlock_wrlock(&__crtl_timers_list_rwlock, 0,0,0,0)#define __crtl_timers_list_unlock crtl_rwlock_unlock(&__crtl_timers_list_rwlock)/* 定时器链表的读写锁 */static LIST_HEAD_UNUSED(__crtl_timers_list_head);/* 定时器列表轮询线程初始化标识位 */static volatile long _unused __crtl_timers_list_poll_task_init_flag = 0; /* 已初始化=1 */static crtl_thread_t _unused __crtl_timer_schedule_threadID;/* 查找一个定时器-线程不安全 */inline static struct crtl_timer_struct * __crtl_timer_getbyid(__crtl_timer_id_t timeid){    /* 入参有误 */    if(unlikely((__crtl_timer_id_t)0==(__crtl_timer_id_t)timeid)) {        crtl_print_err("wrong params error. timeid=%ld\n", timeid);        crtl_assert_fp(stderr, 0);        return NULL;    }    struct crtl_timer_struct *__list_ite_timer = NULL;    struct crtl_timer_struct *_unused __list_ite_next_timer = NULL;        /* 轮询定时器链表 */    list_for_each_entry_safe(__list_ite_timer,__list_ite_next_timer, &__crtl_timers_list_head, list) {//        __crtl_dbg(">>> %lx, %lx\n", __list_ite_timer->timer_id, timeid);        if( __list_ite_timer->timer_id == timeid ) {            return __list_ite_timer;        }        if(list_is_last(&__list_ite_timer->list, &__crtl_timers_list_head)) {//            __crtl_dbg("Last NOde no OK.\n");            return NULL;        }         if( __list_ite_next_timer->timer_id == timeid ) {            return __list_ite_next_timer;        } else {            __list_ite_timer = __list_ite_next_timer;        }    }    __crtl_dbg("Not exist.\n");    return NULL;}/* 添加定时器到定时器链表 */inline static int _unused __crtl_timer_add_to_list(struct crtl_timer_struct *__insert_timer){    struct crtl_timer_struct *__list_ite_timer = NULL;    struct crtl_timer_struct *_unused __list_ite_next_timer = NULL;    struct crtl_timer_struct *_unused __small_timer = NULL;    struct crtl_timer_struct *_unused __big_timer = NULL;    struct timespec time_interval = {0, 0};        /**     *  1.Find the location of insert timer     *     *      __small_timer   __big_timer     *     *  2.Insert new timer     *      __small_timer  __insert_timer  __big_timer     */        /* 如果为空,直接添加 */    if(list_empty(&__crtl_timers_list_head)) {        list_add_tail(&__insert_timer->list, &__crtl_timers_list_head);    /* 如果不为空,查找位置 */    } else {        /* 轮询定时器链表 */        list_for_each_entry_safe(__list_ite_timer,__list_ite_next_timer, &__crtl_timers_list_head, list) {                        /* 比较两个定时器即将到时时间 */            int cmp = crtl_timespec_subabs(&__list_ite_timer->itimerspec_value.it_value,                                            &__insert_timer->itimerspec_value.it_value,                                            &time_interval);            /* 轮询的定时器大于即将插入的定时器,插入到前一个节点*/            if(cmp == CRTL_GT) {                struct crtl_timer_struct *_unused __list_prev_timer = list_prev_entry(__list_ite_timer, list);                list_add(&__insert_timer->list, &__list_prev_timer->list);                break;            }             /* 当 cmp == CRTL_EQ || cmp == CRTL_LT */            /* 如果是最后一个定时器(最后到时的定时器) */            if(list_is_last(&__list_ite_timer->list, &__crtl_timers_list_head)) {                list_add(&__insert_timer->list, &__list_ite_timer->list);                break;                        /* 如果不是最后一个定时器, 同时使用 __list_ite_next_timer */            } else {                            /* 轮询的定时器等于即将插入的定时器,插入*/                if(cmp == CRTL_EQ) {                    list_add(&__insert_timer->list, &__list_ite_timer->list);                    break;                                /* 轮询的定时器小于即将插入的定时器,比较下一个节点 */                } else if(cmp == CRTL_LT) {                    int cmp_next = crtl_timespec_subabs(&__list_ite_next_timer->itimerspec_value.it_value,                                                         &__insert_timer->itimerspec_value.it_value,                                                         &time_interval);                    /* 下一个节点大于或者等于,直接插入 */                    if(cmp_next == CRTL_GT || cmp_next == CRTL_EQ) {                        list_add(&__insert_timer->list, &__list_ite_timer->list);                        break;                    /* 下一个节点小于,继续比较 */                    } else if(cmp_next == CRTL_LT) {                        continue;                    }                }            }    	}    }        return CRTL_SUCCESS;}static void _unused *__crtl_timer_schedule_task_fn(void*arg){//    __crtl_dbg("Start Schdule Timer list. thread id %ld\n", crtl_thread_self());    struct timespec currentTime = {0,0};    struct crtl_timer_struct *__list_ite_timer = NULL;    struct crtl_timer_struct *_unused __list_ite_next_timer = NULL;    struct timespec time_interval = {0, 0};    struct crtl_timer_struct *__this_timer = NULL;            while(1) {        usleep(__CRTL_TIMER_REFRESH_FREQUENCY_NanoSEC/10000);                /* 获取当前时间 */        crtl_gettimeofday_timespec(&currentTime);                        __crtl_timers_list_wrlock;                /* 轮询定时器链表 */        list_for_each_entry_safe(__list_ite_timer,__list_ite_next_timer, &__crtl_timers_list_head, list) {            __this_timer = __list_ite_timer;            if(!list_is_last(&__list_ite_timer->list, &__crtl_timers_list_head)) {                __list_ite_timer = __list_ite_next_timer;            }                                    /* 计算当前时间与定时器超时时间差 */            crtl_timespec_subabs(&__this_timer->itimerspec_value.it_value, &currentTime,  &time_interval);            /* 如果时间差在刷新间隔内,调度定时器 */            if(__CRTL_TIMER_REFRESH_FREQUENCY_NanoSEC >= time_interval.tv_sec*1000000000+time_interval.tv_nsec) {                                /* 调度 */                __this_timer->timer_sche_callback(__this_timer->timer_sche_arg);                /* 从链表中删除这个定时器 */                list_del_init(&__this_timer->list);                            /* 是否为循环定时器 */                if(__this_timer->timer_loop == CRTL_TIMER_LOOP) {                                        /* 获取到期时间:轮询表中将被与GetTimeofDay比较 */                    crtl_timespec_add(&currentTime, &__this_timer->itimerspec_value.it_interval,                                                     &__this_timer->itimerspec_value.it_value);                                        __crtl_timer_add_to_list(__this_timer);                                    } else {                    crtl_mfree1(__this_timer);                }                            }else { /* 如果这个定时器没到时间,后面的定时器全部没有超时 */                break;            }        }        /* 如果删除后定时器列表为空 */        if(list_empty_careful(&__crtl_timers_list_head)) {            __crtl_dbg("Timer List is empty.>>>>>>>>>>\n");            CAS(&__crtl_timers_list_poll_task_init_flag, 1, 0);            __crtl_timers_list_unlock;            break;        }        __crtl_timers_list_unlock;    }    /* 退出线程 */    __crtl_dbg("Terminate Timer Schedule thread.\n");    crtl_thread_exit(NULL);        return NULL;}/* 创建定时器 */__crtl_timer_id_t crtl_timer_create(int is_loop, void (*callback)(void *arg), void *arg, long sec, long nanosec){    /* 入参有误 */    if(unlikely(!callback) || (unlikely(!sec) && unlikely(!nanosec))) {        crtl_print_err("wrong params error.\n");        crtl_assert_fp(stderr, 0);        return 0;    }        /* 类型检测 */    typecheck_fn(__crtl_timer_cb_fn_t, callback);        struct crtl_timer_struct *__timer = crtl_malloc1(1, sizeof(struct crtl_timer_struct));    if(unlikely(!__timer)) {        /* 申请失败,退出 */        crtl_print_err("null pointer error.\n");        crtl_assert_fp(stderr, 0);        return 0;    }    if(is_loop) {        __timer->timer_loop = CRTL_TIMER_LOOP;    } else {        __timer->timer_loop = CRTL_TIMER_NONLOOP;    }#define GEN_TIMERID(paddr) ((__crtl_timer_id_t)paddr)        __timer->timer_id = GEN_TIMERID(__timer);            struct timespec currentTime = {0,0};    /* 计算并保存间隔时间 */    crtl_timespec_generate(&__timer->itimerspec_value.it_interval, sec, nanosec);    /* 获取当前时间 */    crtl_gettimeofday_timespec(&currentTime);        /* 获取到期时间:轮询表中将被与GetTimeofDay比较 */    crtl_timespec_add(&currentTime, &__timer->itimerspec_value.it_interval, &__timer->itimerspec_value.it_value);    /* 置NULL */    __timer->list.next = __timer->list.prev = NULL;    __timer->timer_sche_callback = callback;    __timer->timer_sche_arg = arg;        __crtl_timers_list_wrlock;    /* 添加到定时器链表 */    __crtl_timer_add_to_list(__timer);        /* 创建链表轮询任务 */    if(CAS(&__crtl_timers_list_poll_task_init_flag, 0, 1)) {        __crtl_dbg("__crtl_timers_list_poll_task_init_flag = %ld.\n", __crtl_timers_list_poll_task_init_flag);                /* 创建线程 */        int ret = crtl_thread_create(&__crtl_timer_schedule_threadID, PTHREAD_CREATE_DETACHED, 0,                                       CRTL_THREAD_SCHED_PRIO_HIGHEST, SCHED_RR, PTHREAD_SCOPE_SYSTEM,                                      NULL, 0, 0, __crtl_timer_schedule_task_fn, arg, NULL, NULL);//        int ret = crtl_thread_normal(&__crtl_timer_schedule_threadID, __crtl_timer_schedule_task_fn, arg);        if(ret != CRTL_SUCCESS) {/* 初始化失败 */            crtl_print_err("crtl_thread_create error.\n");            crtl_assert_fp(stderr, 0);            __crtl_timers_list_unlock;            return 0;        }        __crtl_dbg("create timer schedule thread.\n");    }    __crtl_timers_list_unlock;        /* 获取返回值 *///    __crtl_dbg("Create Timer ID: %lx(%lx)(%d)\n", __timer->timer_id, GEN_TIMERID(__timer), sizeof(__crtl_timer_id_t));//    crtl_memprint(stdout, &__timer->timer_id, 8);    return GEN_TIMERID(__timer);}/* 获取定时器时间 */_api int crtl_timer_gettime_interval(__crtl_timer_id_t timerid, long *sec, long *nanosec){    /* 首先找到这个定时器 */    struct crtl_timer_struct *__this_timer = NULL;    __crtl_timers_list_rdlock;    __this_timer = __crtl_timer_getbyid(timerid);    if(unlikely(!__this_timer)) {        crtl_print_err("null pointer error.\n");        crtl_assert_fp(stderr, 0);        __crtl_timers_list_unlock;        return CRTL_ERROR;    }    /* 计算并保存间隔时间 */    *sec = __this_timer->itimerspec_value.it_interval.tv_sec;    *nanosec = __this_timer->itimerspec_value.it_interval.tv_nsec;    __crtl_timers_list_unlock;    return CRTL_SUCCESS;}/* 更新定时器时间 */_api int crtl_timer_settime_interval(__crtl_timer_id_t timerid, long sec, long nanosec){    /* 首先找到这个定时器 */    struct crtl_timer_struct *__this_timer = NULL;    __crtl_timers_list_wrlock;    __this_timer = __crtl_timer_getbyid(timerid);    if(unlikely(!__this_timer)) {        crtl_print_err("null pointer error.\n");        crtl_assert_fp(stderr, 0);        __crtl_timers_list_unlock;        return CRTL_ERROR;    }    /* 计算并保存间隔时间 */    crtl_timespec_generate(&__this_timer->itimerspec_value.it_interval, sec, nanosec);    __crtl_timers_list_unlock;    return CRTL_SUCCESS;}/* 更新定时器 */_api int crtl_timer_nonloop(__crtl_timer_id_t timerid){    /* 首先找到这个定时器 */    struct crtl_timer_struct *__this_timer = NULL;    __crtl_timers_list_wrlock;    __this_timer = __crtl_timer_getbyid(timerid);    if(unlikely(!__this_timer)) {        crtl_print_err("null pointer error.\n");        crtl_assert_fp(stderr, 0);        __crtl_timers_list_unlock;        return CRTL_ERROR;    }    __this_timer->timer_loop = CRTL_TIMER_NONLOOP;        __crtl_timers_list_unlock;    return CRTL_SUCCESS;}/* 删除定时器 */_api int crtl_timer_delete(__crtl_timer_id_t timerid){    struct crtl_timer_struct *__this_timer = NULL;    __crtl_timers_list_wrlock;    __this_timer = __crtl_timer_getbyid(timerid);    if(unlikely(!__this_timer)) {        crtl_print_err("null pointer error.\n");        crtl_assert_fp(stderr, 0);        __crtl_timers_list_unlock;        return CRTL_ERROR;    }    /* 从链表中删除这个定时器 */    list_del_init(&__this_timer->list);    __crtl_timers_list_unlock;        crtl_mfree1(__this_timer);    return CRTL_SUCCESS;}//

 

转载地址:http://vbpaf.baihongyu.com/

你可能感兴趣的文章
【Java】【15】判断url对应的图片是否存在
查看>>
【Java】【22】读写properties文件
查看>>
【Spring】【1】mybatis spring的自动扫描配置
查看>>
【Java】【25】去除空格
查看>>
【其他】【PL/SQL Developer】【2】报错Initialization error Could not load ".../oci.dll"解决方法...
查看>>
【Java】【28】提高List的removeAll方法的效率
查看>>
【JS】【28】让输入框只能输入正整数
查看>>
【记录】【4】各种工具
查看>>
【JS】【31】读取json文件
查看>>
Ubuntu Boost 编译
查看>>
MySQL中的行级锁,表级锁,页级锁
查看>>
ORACLE 修改SID
查看>>
OpenCV模块分析(转)
查看>>
聊聊我对写好程序的认识
查看>>
OpenSSL源代码学习[转]
查看>>
插件原理2[转自CSDN]
查看>>
COM编程快速入门[转自VCbase]
查看>>
VBA得到word中的超链接
查看>>
ComBSTR的使用
查看>>
硬回车与软回车[转]
查看>>