随想录(编写用户侧定时器)

本文介绍了一个基于秒级粒度的自制定时器实现方法,支持单次及循环两种模式,并通过互斥操作确保移植性,同时提供了类似Linux定时器的接口。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】


定时器是我们在平时开发中经常使用到的工具,特别是在协议的编写上更是必不可少的组成部分。虽然系统本身给我们提供了定时器,但是有的时候,我们也想自己编写一个粗粒度的定时器,比如说在单元测试的时候。大家只要看到下面的实例代码,其实就会发现,只要利用一下sleep函数,编写属于自己的定时器原来不是一件复杂的事情。当然,在实现自己的定时器之前,你需要明白自己的定时器应该设计成什么样子?比如说,


(1)定时器是否需要做互斥处理?

(2)定时器支持那几种类型?

(3)定时器支持的最大粒度是多少?有没有什么限制?

(4)定时器的接口是什么?

(5)定时器怎么遍历、组织和运行?


下面的代码就是我自己练习时编写的一个定时器,具有下面几个特点:

(1)支持1s为基本单位的定时操作;

(2)支持定时器互斥操作,适合移植;

(3)支持单次和循环两种定时器;

(4)tick计数和定时函数处理是由不同线程完成;

(5)定时器接口简单,和linux定时器接口基本一致。


最后贴出自己的定时器代码,欢迎大家多提宝贵意见。

struct TIMER
{
	int type;
	int state;
	int count;
	int expire;
	void (*func)(void*);
	void* param;
	struct LINK_NODE node;
	char name[MAX_NAME_LEN];
};

#define MAX_NAME_LEN 16
#define TIMER_LOCK_INIT()
#define TIMER_LOCK(sem)
#define TIMER_UNLOCK(sem)

#define STATUS int
#define MAX_TIMER_VALUE (7*24*3600)

enum
{
	SINGLE_SHOT = 1,
	RECYCLE_TYPE = 2
};

enum
{
	TIMER_ACTIVE = 1,
	TIMER_NOT_ACTIVE = 2
};

static int g_timer_count;
static struct LINK_NODE g_timer_head;
static HANDLE h_timer_sem;

void timer_init()
{
	g_timer_count = 0;
	link_init(&g_timer_head);
	h_timer_sem = TIMER_LOCK_INIT();
}

STATUS alloc_timer(const char* name, int type, int count, void (*func)(void*), void* param)
{
	struct LINK_NODE* p_node;
	struct TIMER* p_timer;

	if(NULL == name || NULL == func || NULL == param)
	{
		return FALSE;
	}

	if(strlen(name) >= MAX_NAME_LEN)
	{
		return FALSE;
	}

	if(SINGLE_SHOT != type && RECYCLE_TYPE != type)
	{
		return FALSE;
	}

	if(MAX_TIMER_VALUE < count || 0 == count)
	{
		return FALSE;
	}
	
	TIMER_LOCK(h_timer_sem);
	for(p_node = g_timer_head.next; NULL != p_node; p_node = p_node->next)
	{
		p_timer = GET_DATA_BY_ADDRESS(p_node, struct TIMER, node);
		if(0 == strncmp(p_timer->name, name, strlen(name)))
		{
			TIMER_UNLOCK(h_timer_sem);
			return FALSE;
		}
	}
	
	p_timer = (struct TIMER*)malloc(sizeof(struct TIMER));
	if(NULL == p_timer)
	{
		TIMER_UNLOCK(h_timer_sem);
		return FALSE;
	}

	memset(p_timer, 0, sizeof(struct TIMER));
	strncpy(p_timer->name, name, strlen(name));
	p_timer->type = type;
	p_timer->count = count;
	p_timer->func = func;
	p_timer->param = param;
	p_timer->state = TIMER_NOT_ACTIVE;

	add_node_into_link(&p_timer->node, &g_timer_head);
	TIMER_UNLOCK(h_timer_sem);
	
	return TRUE;
}


STATUS timer_start(const char* name)
{
	struct LINK_NODE* p_node;
	struct TIMER* p_timer;

	if(NULL == name || strlen(name) >= MAX_NAME_LEN)
	{
		return FALSE;
	}

	TIMER_LOCK(h_timer_sem);
	for(p_node = g_timer_head.next; NULL != p_node; p_node = p_node->next)
	{
		p_timer = GET_DATA_BY_ADDRESS(p_node, struct TIMER, node);
		if(0 == strncmp(p_timer->name, name, strlen(name)))
		{
			break;
		}
	}

	if(NULL == p_node)
	{
		TIMER_UNLOCK(h_timer_sem);
		return FALSE;
	}

	if(TIMER_NOT_ACTIVE == p_timer->state)
	{
		p_timer->expire = g_timer_count + p_timer->count;
		p_timer->state = TIMER_ACTIVE;
	}

	TIMER_UNLOCK(h_timer_sem);
	return TRUE;
}


STATUS timer_del(const char* name)
{	
	struct LINK_NODE* p_node;
	struct TIMER* p_timer;

	if(NULL == name || strlen(name) >= MAX_NAME_LEN)
	{
		return FALSE;
	}

	TIMER_LOCK(h_timer_sem);
	for(p_node = g_timer_head.next; NULL != p_node; p_node = p_node->next)
	{
		p_timer = GET_DATA_BY_ADDRESS(p_node, struct TIMER, node);
		if(0 == strncmp(p_timer->name, name, strlen(name)))
		{
			break;
		}
	}

	if(NULL == p_node)
	{
		TIMER_UNLOCK(h_timer_sem);
		return FALSE;
	}

	delete_node_from_link(&p_timer->node);
	TIMER_UNLOCK(h_timer_sem);
	free(p_timer);
	return TRUE;
}


void timer_run()
{
	struct LINK_NODE* p_node;
	struct TIMER* p_timer;
	int count;

	while(1)
	{
		count = g_timer_count;
		TIMER_LOCK(h_timer_sem);
		for(p_node = g_timer_head.next; NULL != p_node; p_node = p_node->next)
		{
			p_timer = GET_DATA_BY_ADDRESS(p_node, struct TIMER, node);
			if(TIMER_ACTIVE == p_timer->state && count > p_timer->expire)
			{
				p_timer->func(p_timer->param);

				if(SINGLE_SHOT == p_timer->type)
				{
					p_timer->state = TIMER_NOT_ACTIVE;
				}
				else
				{
					p_timer->expire = count + p_timer->count;
				}
			}
		}

		TIMER_UNLOCK(h_timer_sem);
		sleep(1);
	}
}


void tick_process()
{
	while(1)
	{
		g_timer_count ++;
		sleep(1);
	}
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值