c语言实现简单定时回调任务系统

  • Post author:
  • Post category:其他


业务上有较多的定时运行功能,为了代码的通用性,自己实现一个简单的回调接口。

头文件如下:

#ifndef __MOD_TIMER_H__
#define __MOD_TTIMER_H__

#include "typedef.h"

typedef void (*mod_timer_task_callback)(void *data);
typedef u64 (*mod_timer_get_ms_callback)();

i32 mod_timer_init(mod_timer_get_ms_callback func);
void mod_timer_run();

//注意,执行回调函数有加锁,所以回调函数中不要有延时、休眠操作
//mode 0 无限循环,其他循环次数
u32 mod_timer_regist(u32 timeout, mod_timer_task_callback run, void *user_data, u32 mode);
void mod_timer_delete(u32 id);

#endif

具体实现如下:

#include "typedef.h"
#include "platform.h"
#include "list.h"
#include "mod_timer.h"

typedef struct
{
    struct list_head list;       // 链表
    mod_timer_task_callback run; // 任务回调
    u32 id;                      // 定时任务id
    u64 lastMs;                  // 上一次执行的时间
    u32 timeout;                 // 定时的超时时间,ms
    u32 cnt;                     //循环次数,多次循环时使用
    u32 mode;                    // 定时任务的工作模式,2种工作模式。初始化为0 则为循环模式,其他值则为循环次数
    void *data;                  // 定时任务的上下文1
} ModTimerTask;                  // 定时任务节点

typedef struct
{
    struct list_head list;                    // 任务列表
    os_mutex lock;                            // 互斥锁,用于链表操作
    mod_timer_get_ms_callback get_current_ms; // 获取ms值的接口
    u32 id;                                   //新任务注册时生成的id,依次增加
} ModTimerHandle;                             // 定时器实例

static ModTimerHandle timerHandle;

//定时器初始化
i32 mod_timer_init(mod_timer_get_ms_callback func)
{
    INIT_LIST_HEAD(&timerHandle.list); // 链表初始化
    timerHandle.get_current_ms = func;
    os_mutex_init(&timerHandle.lock, NULL);
    timerHandle.id = 1;
    return 0;
}

//定时器轮询调度,由main函数调用
void mod_timer_run()
{
    struct list_head *item;
    struct list_head *next;

    os_mutex_lock(&timerHandle.lock);

    list_for_each_safe(item, next, &timerHandle.list)
    {
        ModTimerTask *task = list_entry(item, ModTimerTask, list);
        u64 currentMs = timerHandle.get_current_ms();
        if (((u32)(currentMs - task->lastMs) >= (u32)task->timeout))
        {

            if (task->run != NULL)
            {
                task->run(task->data);
            }

            task->lastMs = currentMs;

            if (task->mode > 0)
            {
                task->cnt++;
                if (task->cnt >= task->mode)
                {
                    list_del(item);
                }
            }
        }
    }

    os_mutex_unlock(&timerHandle.lock);
}

//注册定时任务
u32 mod_timer_regist(u32 timeout, mod_timer_task_callback run, void *user_data, u32 mode)
{
    ModTimerTask *task = os_malloc(sizeof(ModTimerTask));
    if (task == NULL)
    {
        return 0;
    }

    task->id = timerHandle.id++;
    task->run = run;
    task->lastMs = timerHandle.get_current_ms();
    task->timeout = timeout;
    task->cnt = 0;
    task->mode = mode;
    task->data = user_data;

    os_mutex_lock(&timerHandle.lock);

    list_add_tail(&task->list, &timerHandle.list);

    os_mutex_unlock(&timerHandle.lock);

    return task->id;
}

//删除定时任务
void mod_timer_delete(u32 id)
{
    struct list_head *item;
    struct list_head *next;

    os_mutex_lock(&timerHandle.lock);

    list_for_each_safe(item, next, &timerHandle.list)
    {
        ModTimerTask *task = list_entry(item, ModTimerTask, list);

        if (task->id == id)
        {
            list_del(item);
        }
    }
    os_mutex_unlock(&timerHandle.lock);
}

使用时现在main函数中调用mod_timer_init初始化定时器模块,需要传入一个取得本地时间(ms)的接口,然后在main函数的while(1)中调用mod_timer_run()。注册回调任务时调用:mod_timer_regist函数,第一个参数是定时时间(ms),第二个是回调函数,第三个是需要传给回调函数执行的参数,最后一个是模式,mode 0 无限循环,其他循环次数

mod_timer_regist(60 * 1000, gw_send_system_info_task, NULL, 0);

linux下取得毫秒函数为:

#include <unistd.h>
#include <sys/time.h>

u64 get_time_msec()

{
    struct timeval val;
    gettimeofday(&val, NULL);
    return (u64)val.tv_sec * 1000 + (u64)val.tv_usec / 1000;
}



版权声明:本文为yeamon原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。