C程序设计:基于双向链表的软件定时器

1.简介

基于双向链表的软件定时器是一种常见的实现方式,它可以在操作系统或应用程序中用于管理定时任务。

双向链表是一种数据结构,它包含指向前一个节点和后一个节点的指针。在软件定时器的实现中,每个定时任务可以表示为一个节点,节点中包含定时任务的信息,如定时时间、回调函数等。

软件定时器可以被添加到硬件定时器中,主线程循环中,另开线程中。

2.头文件

#ifndef SOFT_TIMER_H
#define SOFT_TIMER_H

#include "list.h"

typedef int (*timer_callback)(int msg_1, int msg_2); //定时器回调函数

typedef enum _TimerStatusType
{
    TST_STOP    = 0x00, //停止
    TST_RUNNING = 0x01, //运行
    TST_TIMEOUT = 0x02, //超时
} TimerStatusType;

typedef enum _TimerModeType
{
    TMT_ONE  = 0x00, //单次
    TMT_LOOP = 0x01, //循环
} TimerModeType;

typedef enum _TimerPriorityType
{
	TPT_REALTIME    = 0x00,   //实时
	TPT_LOWLEVEL    = 0x01,   //低优先级
} TimerPriorityType;

typedef struct _TimerList
{
	int timer_id;			    //定时器编号
	TimerPriorityType level;    //定时器响应优先级
	TimerStatusType status;	    //定时器状态
	TimerModeType mode;		    //模式

	unsigned char r;

	timer_callback callback;          //注册的回调函数
    int msg_1;                        //回调函数参数1
    int msg_2;                        //回调函数参数2

	unsigned long long TimerCycle;	  //配置的定时周期 
	unsigned long long nextTime;      //响应时间点

	struct list_head node;	          //定时器链表
} TimerList;

typedef struct _TimerListQueue
{
	int cnt;                            //数量    
	unsigned long long nextTime;	    //响应时间点
	struct list_head listHead;          //软件定时器队列头
} TimerListQueue;

void cj_softTimer_interrupt_task();
void cj_softTimer_init();
bool cj_softTimer_creat(timer_callback func,  int msg_1, int msg_2, TimerModeType type, TimerPriorityType level, unsigned int id);
bool cj_softTimer_break(unsigned int id);
bool cj_softTimer_start(unsigned int id, unsigned int millisecond);
bool cj_softTimer_stop(unsigned int id);

#endif

3.实现代码


#include "softtimer.h"
#include "cjevent.h"
#include <esp_timer.h>
#include <string.h>

static TimerListQueue s_timerListQueue;

extern EventListQueue g_normalEventQueue;   

/* 获取下一次 软件定时器任务中断响应的时间点 */
static unsigned long long getTimerNextResponseTime(TimerListQueue *queue, unsigned int *nodeCnt)
{
	TimerList *lister = NULL;
	*nodeCnt = 0;
	unsigned long long responseTime_min = 0;
	
    list_for_each_entry_reverse(lister, TimerList, &queue->listHead, node)
	{
		if (lister->status == TST_RUNNING)
		{ 
			*nodeCnt += 1;
            /* next_valid_min 取链表中 最小的一个*/
            if (responseTime_min == 0 || responseTime_min >= lister->nextTime)
			{
				responseTime_min = lister->nextTime;
			}
		}
	}

	if (*nodeCnt > 0)
		return responseTime_min;
    else
        return queue->nextTime;
}

static void updateTimerList_nextTime(TimerListQueue *queue)
{
	unsigned long long nextTime;
	unsigned int runningSoftTimerCnt = 0;

    /* 获取软件定时器链表里面定时器任务中的最小一个的响应时间 */
	nextTime = getTimerNextResponseTime(queue, &runningSoftTimerCnt);
	if(runningSoftTimerCnt > 0)
    {
        if (nextTime != queue->nextTime)
        {
            queue->nextTime = nextTime;
        }
	}
}

//定时器超时之后的处理函数
static void timerListProcess(TimerListQueue *queue)
{
	TimerList *lister = NULL;
	list_for_each_entry_reverse(lister, TimerList, &queue->listHead, node)
	{
		if (lister->status == TST_TIMEOUT)
		{ 
			if (lister->callback != NULL)
			{			
				if (lister->level == TPT_LOWLEVEL)
				{ 
                    /* 低优先级定时器任务可以推入事件管理器中 */
                    EventStaus status;
                    status.fun = lister->callback;
                    status.status_1 = lister->msg_1;
                    status.status_2 = lister->msg_2;
                    addToEventList(&g_normalEventQueue, ET_TIMER, &status, NULL);
				}
				else
				{
                    /* 高优先级 定时器任务 */
					lister->callback(lister->msg_1, lister->msg_2); 
				}
			}
            /* 判断是否是循环定时器任务 */
			if(lister->mode == TMT_LOOP)
			{ 
                lister->status = TST_RUNNING;
				lister->nextTime = get_now_time() + lister->TimerCycle;
			}
            else
            {
			    lister->status = TST_STOP;
            }
		}
	}
    /* 更新定时器链表里下次响应的时间 */
	updateTimerList_nextTime(queue);

	return;
}

//中断处理函数
static void timer_callback_fun()
{
    TimerList *lister = NULL;
    bool isNeedProcess = false;

    unsigned long long nowTime = get_now_time();

    list_for_each_entry_reverse(lister, TimerList, &s_timerListQueue.listHead, node)
	{
		if (lister->status == TST_RUNNING)
		{ 
			if (nowTime >= lister->nextTime)
			{ 
				lister->status = TST_TIMEOUT;
				isNeedProcess = true;
			}
		}
	}
	if (isNeedProcess)
	{
		timerListProcess(&s_timerListQueue);
	}
}

void cj_softTimer_interrupt_task()
{
	if(s_timerListQueue.nextTime >  get_now_time())
	{
		return;
	}
    else
    {
        timer_callback_fun();
    }
	return;
}

void cj_softTimer_init()
{
    /* 初始化链表头 */
	memset(&s_timerListQueue.listHead, 0, sizeof(struct list_head));
	INIT_LIST_HEAD(&s_timerListQueue.listHead);

    /* 其他参数初始化 */
	s_timerListQueue.cnt = 0;
	s_timerListQueue.nextTime = get_now_time();
}

bool cj_softTimer_creat(timer_callback func,  int msg_1, int msg_2,
						TimerModeType type, TimerPriorityType level, unsigned int id)
{
	TimerList *lister = NULL;
	list_for_each_entry_reverse(lister, TimerList, &s_timerListQueue.listHead, node)
	{
		/* 发现id号存在 则直接返回失败 */
		if (lister->timer_id == id)
		{
			printf("timer id = %d is aready creat !\n", id);
			return false;
		}
	}

	TimerList *newTimer = (TimerList *)malloc(sizeof(TimerList));
	memset(newTimer, 0, sizeof(TimerList));

	newTimer->timer_id = id;
	newTimer->level = level;
	newTimer->status = TST_STOP;
	newTimer->mode = type;

	newTimer->callback = func;
	newTimer->msg_1 = msg_1;
	newTimer->msg_2 = msg_2;

	s_timerListQueue.cnt += 1;
	list_add(&(newTimer->node), &(s_timerListQueue.listHead));

	return true;
}

bool cj_softTimer_break(unsigned int id)
{
	TimerList *lister = NULL;
	list_for_each_entry_reverse(lister, TimerList, &s_timerListQueue.listHead, node)
	{
		if (lister->timer_id == id)
		{
			s_timerListQueue.cnt -= 1;
			list_del(&lister->node);
			free(lister);
			return true;
		}
	}
	return false;
}

bool cj_softTimer_start(unsigned int id, unsigned int millisecond)
{
	TimerList *lister = NULL;
	list_for_each_entry_reverse(lister, TimerList, &s_timerListQueue.listHead, node)
	{
		if (lister->timer_id == id)
		{
			if(lister->status == TST_RUNNING)
			{
				/* 当前如果正在运行 不允许重复启动 */
				printf("timer id = %d is ready running !\n", id);
				return false;
			}
			break;;
		}
	}

	if(lister == NULL)
		return false;

	unsigned long long timer_now = get_now_time();
	unsigned long long us_second = millisecond * 1000;

	lister->TimerCycle = us_second;
	lister->nextTime = timer_now + us_second;
	lister->status = TST_RUNNING;

    /* 跟新下次中断的时间 */
	updateTimerList_nextTime(&s_timerListQueue); 

	return true;
}

bool cj_softTimer_stop(unsigned int id)
{
	TimerList *lister = NULL;
	list_for_each_entry_reverse(lister, TimerList, &s_timerListQueue.listHead, node)
	{
		if (lister->timer_id == id)
		{
			lister->status = TST_STOP;
			return true;
		}
	}

	return false;
}

4.示例

int temp_callBack(int msg_1, int msg_2)
{
    printf("hello world !\n");
    return 0;
}

int main()
{
    ...;
    cj_softTimer_init();
    cj_softTimer_creat(temp_callBack, 0, 0, TMT_LOOP, TPT_LOWLEVEL, 0);
    cj_softTimer_start(0, 2000);
    while(1)
    {
        cj_softTimer_interrupt_task();
        ...;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值