高性能秒级定时器实现源码

1、本文展示秒级定时器的源码,源码是封装成C++类,然后再次封装成API函数的方式。

     用户开发手册地址:https://blog.csdn.net/freeland008/article/details/107508749

 

2、TimerVM.h和TimerVM.cpp是用c++类的方式实现了秒级时钟的封装,TimerMng.h、TimerMng.cpp实现了二次封装,更方便开发人员直接使用。

3、总体实现思路是使用双时间轮数组交换的方式。

 

4、TimerVM.h

#ifndef TIMERVM_H
#define TIMERVM_H

#include <time.h>

typedef void* HANDLE;

typedef struct _TIMERITEM
{	
	unsigned int dwTimes;	
	unsigned int dwTimeOut;
	time_t dtExpire;
	void* fp;
	void* pPara;			
	void* pPosArray;

	_TIMERITEM* pPrev;
	_TIMERITEM* pNext;
}TIMERITEM;
typedef TIMERITEM* LPTIMERITEM;

typedef struct _TIMERARRAY
{
	time_t dtStart;
	HANDLE* hArray;
	_TIMERARRAY()
	{
		dtStart = 0;
		hArray = NULL;
	}
}TIMERARRAY;
typedef TIMERARRAY* LPTIMERARRAY;

class CTimerMng
{ 
private:
	TIMERARRAY m_pTimerArrayA;
	TIMERARRAY m_pTimerArrayB;
	time_t m_dtLastCheck;
	int m_nArraySize;
public:
	LPTIMERARRAY m_pArrayOld;
	LPTIMERARRAY m_pArrayNew;
private:
	size_t m_nCount;	
	int m_nTimerOutCount;
	int m_nSetTimerCount;
	int m_nResetCycleTimerCount;
	int m_nResetOverTimerCount;
public:	
	LPTIMERITEM m_pResetList;
	LPTIMERITEM m_pOverList;
public:
	CTimerMng();
	~CTimerMng();
public:
	int Init(int nArraySize, time_t dtNow);
	int Destroy();
	LPTIMERITEM SetTimer(time_t dtNow, unsigned int dwTimeOut, unsigned int dwTimes, void* fp, void* pPara);	
	void ResetTimerCycle(LPTIMERITEM pItem);		
	void ResetTimerOver(LPTIMERITEM pItem);	
	void KillTimer(LPTIMERITEM pItem);
	void CheckTimeOut(time_t dtNow);
	void OnProcTimeOut(LPTIMERITEM pItem, time_t dtNow);		
	size_t GetCount(){return m_nCount;};
};

#endif

 

5、TimerVM.cpp

 

#include <stdio.h>
#include <stdlib.h>
#include "TimerVM.h"
#include "TimerMng.h"

CTimerMng :: CTimerMng()
{
	m_nCount = 0;		

	m_nTimerOutCount = 0;
	m_nSetTimerCount = 0;
	m_nResetCycleTimerCount = 0;
	 m_nResetOverTimerCount = 0;

	m_dtLastCheck = 0;
	m_pResetList = NULL;
	m_pOverList = NULL;

	m_pTimerArrayA.hArray = NULL;
	m_pTimerArrayB.hArray = NULL;
}

CTimerMng :: ~CTimerMng()
{
	Destroy();
}

int CTimerMng :: Init(int nArraySize, time_t dtNow)
{
	m_nArraySize = nArraySize;	

	m_pTimerArrayA.hArray = new HANDLE[m_nArraySize];
	int i;
	for (i = 0; i < m_nArraySize; i++)
	{
		m_pTimerArrayA.hArray[i] = NULL;
	}

	m_pTimerArrayB.hArray = new HANDLE[m_nArraySize];
	for (i = 0; i < m_nArraySize; i++)
	{
		m_pTimerArrayB.hArray[i] = NULL;
	}

	m_pArrayOld = &m_pTimerArrayA;
	m_pArrayNew = &m_pTimerArrayB;

	m_pArrayOld->dtStart = dtNow;
	m_pArrayNew->dtStart = m_pArrayOld->dtStart + m_nArraySize;

	m_dtLastCheck = dtNow;
	//		

	return 0;
}
/*
void CTimerMng :: Align(time_t dtNow)
{
	m_pArrayOld->dtStart = dtNow;
	m_pArrayNew->dtStart = m_pArrayOld->dtStart + m_nArraySize;

	m_dtLastCheck = dtNow;
}*/

int CTimerMng :: Destroy()
{	
	if(m_pTimerArrayA.hArray != NULL)
	{
		delete[] m_pTimerArrayA.hArray;
		m_pTimerArrayA.hArray = NULL;
	}

	if(m_pTimerArrayB.hArray != NULL)
	{
		delete[] m_pTimerArrayB.hArray;
		m_pTimerArrayB.hArray = NULL;
	}

	return 0;
}

LPTIMERITEM CTimerMng :: SetTimer(time_t dtNow, unsigned int nElapse, unsigned int dwTimes, void* fp, void* pPara)
{	
	if(nElapse == 0)
	{
		return NULL;
	}

	time_t dtExpire;
	dtExpire = dtNow + nElapse;

	LPTIMERITEM pItem;
	pItem = (LPTIMERITEM)malloc(sizeof(TIMERITEM));	

	pItem->dtExpire = dtExpire;
	pItem->dwTimeOut = nElapse;
	pItem->dwTimes = dwTimes;	
	pItem->pPara = pPara;	
	pItem->fp = fp;

	pItem->pPrev = NULL;
	pItem->pNext = NULL;

	void* pAddr;	
	if(dtExpire >= m_pArrayNew->dtStart)
	{	
		int nIndex;
		nIndex = dtExpire - m_pArrayNew->dtStart;		
		nIndex = nIndex%m_nArraySize;		

		if(m_pArrayNew->hArray[nIndex] == NULL)
		{				
			m_pArrayNew->hArray[nIndex] = pItem;
		}
		else			
		{
			LPTIMERITEM pTmp;
			pTmp = (LPTIMERITEM)(m_pArrayNew->hArray[nIndex]);			
			pItem->pNext = pTmp;
			pTmp->pPrev = pItem;
			m_pArrayNew->hArray[nIndex] = pItem;
		}		

		pAddr = &(m_pArrayNew->hArray[nIndex]);
	}
	else
	{		
		int nIndex;
		nIndex = dtExpire - m_pArrayOld->dtStart;	

		if(m_pArrayOld->hArray[nIndex] == NULL)
		{			
			m_pArrayOld->hArray[nIndex] = pItem;
		}
		else
		{			
			LPTIMERITEM pTmp;
			pTmp = (LPTIMERITEM)(m_pArrayOld->hArray[nIndex]);			
			pItem->pNext = pTmp;
			pTmp->pPrev = pItem;
			m_pArrayOld->hArray[nIndex] = pItem;
		}			

		pAddr = &(m_pArrayOld->hArray[nIndex]);
	}
	//

	pItem->pPosArray = pAddr;

	m_nCount++;

	m_nSetTimerCount++;

	return pItem;
}


void CTimerMng :: ResetTimerOver(LPTIMERITEM pItem)
{	
	void* pAddr;	
	if(pItem->dtExpire >= m_pArrayNew->dtStart)
	{		
		int nIndex;
		nIndex = pItem->dtExpire - m_pArrayNew->dtStart;	
		nIndex = nIndex%m_nArraySize;	

		if(m_pArrayNew->hArray[nIndex] == NULL)
		{				
			m_pArrayNew->hArray[nIndex] = pItem;
			pItem->pPrev = NULL;
			pItem->pNext = NULL;
		}
		else			
		{			
			LPTIMERITEM pTmp;
			pTmp = (LPTIMERITEM)(m_pArrayNew->hArray[nIndex]);
			pItem->pNext = pTmp;
			pItem->pPrev = NULL;
			pTmp->pPrev = pItem;
			m_pArrayNew->hArray[nIndex] = pItem;
		}		

		pAddr = &(m_pArrayNew->hArray[nIndex]);
	}
	else
	{		
		int nIndex;
		nIndex = pItem->dtExpire - m_pArrayOld->dtStart;	

		if(m_pArrayOld->hArray[nIndex] == NULL)
		{			
			m_pArrayOld->hArray[nIndex] = pItem;
			pItem->pPrev = NULL;
			pItem->pNext = NULL;
		}
		else
		{			
			LPTIMERITEM pTmp;
			pTmp = (LPTIMERITEM)(m_pArrayOld->hArray[nIndex]);			
			pItem->pNext = pTmp;
			pItem->pPrev = NULL;
			pTmp->pPrev = pItem;
			m_pArrayOld->hArray[nIndex] = pItem;
		}			

		pAddr = &(m_pArrayOld->hArray[nIndex]);
	}	
	
	pItem->pPosArray = pAddr;	

	m_nResetOverTimerCount++;
}

void CTimerMng :: ResetTimerCycle(LPTIMERITEM pItem)
{		
	time_t dtExpire;
	dtExpire = pItem->dtExpire + pItem->dwTimeOut;
	//
	void* pAddr;	
	if(dtExpire >= m_pArrayNew->dtStart)
	{
		int nIndex;
		nIndex = dtExpire - m_pArrayNew->dtStart;		
		nIndex = nIndex%m_nArraySize;		

		if(m_pArrayNew->hArray[nIndex] == NULL)
		{				
			m_pArrayNew->hArray[nIndex] = pItem;
			pItem->pPrev = NULL;
			pItem->pNext = NULL;
		}
		else			
		{			
			LPTIMERITEM pTmp;
			pTmp = (LPTIMERITEM)(m_pArrayNew->hArray[nIndex]);			
			pItem->pNext = pTmp;
			pItem->pPrev = NULL;
			pTmp->pPrev = pItem;
			m_pArrayNew->hArray[nIndex] = pItem;
		}		

		pAddr = &(m_pArrayNew->hArray[nIndex]);
	}
	else
	{
		int nIndex;
		nIndex = dtExpire - m_pArrayOld->dtStart;

		if(m_pArrayOld->hArray[nIndex] == NULL)
		{			
			m_pArrayOld->hArray[nIndex] = pItem;
			pItem->pPrev = NULL;
			pItem->pNext = NULL;
		}
		else
		{			
			LPTIMERITEM pTmp;
			pTmp = (LPTIMERITEM)(m_pArrayOld->hArray[nIndex]);			
			pItem->pNext = pTmp;
			pItem->pPrev = NULL;
			pTmp->pPrev = pItem;
			m_pArrayOld->hArray[nIndex] = pItem;
		}			

		pAddr = &(m_pArrayOld->hArray[nIndex]);
	}
	//	
	pItem->dtExpire = dtExpire;		

	pItem->pPosArray = pAddr;	

	m_nResetCycleTimerCount++;
}

void CTimerMng :: KillTimer(LPTIMERITEM pItem)
{
	void* pAddr;
	pAddr = pItem->pPosArray;

	if(pItem->pPrev == NULL)
	{
		if(pItem->pNext == NULL)
		{
			*(size_t *)pAddr = NULL;	
		}		
		else
		{
			LPTIMERITEM pNext;
			pNext = pItem->pNext;
			pNext->pPrev = NULL;
			*(size_t *)pAddr = (size_t)pNext;	
		}
	}
	else
	{
		if(pItem->pNext == NULL)
		{
			LPTIMERITEM pPrev;
			pPrev = pItem->pPrev;
			pPrev->pNext = NULL;			
		}		
		else
		{
			LPTIMERITEM pNext;
			pNext = pItem->pNext;

			LPTIMERITEM pPrev;
			pPrev = pItem->pPrev;

			pPrev->pNext = pNext;
			pNext->pPrev = pPrev;
		}
	}
	
	free(pItem);	

	m_nCount--;
}

void CTimerMng :: CheckTimeOut(time_t dtNow)
{	
	if(dtNow >= m_pArrayNew->dtStart)
	{
		if(m_dtLastCheck < m_pArrayNew->dtStart)	
		{
			time_t dtTime;
			for(dtTime = m_dtLastCheck + 1; dtTime < m_pArrayNew->dtStart; dtTime++)
			{					
				int nIndex;
				nIndex = dtTime - m_pArrayOld->dtStart;				
				if(nIndex >= m_nArraySize || nIndex < 0)
				{
					break;
				}
				
				HANDLE hList;
				hList = m_pArrayOld->hArray[nIndex];
				if(hList != NULL)
				{					
					OnProcTimeOut((LPTIMERITEM)hList, dtNow);
					m_pArrayOld->hArray[nIndex] = NULL;
				}								
			}						

			for(dtTime = m_pArrayNew->dtStart; dtTime <= dtNow; dtTime++)
			{								
				int nIndex;
				nIndex = dtTime - m_pArrayNew->dtStart;				
				if(nIndex >= m_nArraySize || nIndex < 0)
				{
					break;
				}
				
				HANDLE hList;
				hList = m_pArrayNew->hArray[nIndex];
				if(hList != NULL)
				{					
					OnProcTimeOut((LPTIMERITEM)hList, dtNow);
					m_pArrayNew->hArray[nIndex] = NULL;
				}								
			}			
		}
		else
		{
			time_t dtTime;
			for(dtTime = m_dtLastCheck + 1; dtTime <= dtNow; dtTime++)
			{			
				int nIndex;
				nIndex = dtTime - m_pArrayNew->dtStart;				
				if(nIndex >= m_nArraySize || nIndex < 0)
				{
					break;
				}
				
				HANDLE hList;
				hList = m_pArrayNew->hArray[nIndex];
				if(hList != NULL)
				{					
					OnProcTimeOut((LPTIMERITEM)hList, dtNow);
					m_pArrayNew->hArray[nIndex] = NULL;
				}										
			}			
		}
		//
		LPTIMERARRAY pTmp;
		pTmp = m_pArrayOld;
		m_pArrayOld = m_pArrayNew;
		m_pArrayNew = pTmp;
		m_pArrayNew->dtStart = m_pArrayOld->dtStart + m_nArraySize;
		//
	}
	else
	{
		time_t dtTime;
		for(dtTime = m_dtLastCheck + 1; dtTime <= dtNow; dtTime++)
		{		
			int nIndex;
			nIndex = dtTime - m_pArrayOld->dtStart;			
			if(nIndex >= m_nArraySize || nIndex < 0)
			{
				break;
			}
			
			HANDLE hList;
			hList = m_pArrayOld->hArray[nIndex];
			if(hList != NULL)
			{				
				OnProcTimeOut((LPTIMERITEM)hList, dtNow);
				m_pArrayOld->hArray[nIndex] = NULL;
			}								
		}		
	}

	m_dtLastCheck = dtNow;
	//	
	while(m_pResetList != NULL)
	{
		LPTIMERITEM pItem;		
		pItem = m_pResetList;		
		m_pResetList = m_pResetList->pNext;
		ResetTimerCycle(pItem);
	}	
	
	while(m_pOverList != NULL)
	{
		LPTIMERITEM pItem;		
		pItem = m_pOverList;		
		m_pOverList = m_pOverList->pNext;		
		ResetTimerOver(pItem);					
	}	
}

void CTimerMng :: OnProcTimeOut(LPTIMERITEM pItem, time_t dtNow)
{	
	while(pItem != NULL)
	{
		LPTIMERITEM pTmp;
		pTmp = pItem->pNext;

		if(dtNow < pItem->dtExpire)
		{				
			if(m_pOverList == NULL)
			{
				m_pOverList = pItem;
				m_pOverList->pNext = NULL;
			}
			else
			{				
				pItem->pNext = m_pOverList;
				m_pOverList = pItem;
			}
			pItem = pItem->pNext;
			pItem = pTmp;
			continue;
		}	
		
		//
		LPTIMEROUTPROC(pItem->fp)(this, pItem, pItem->pPara);
		//
		if(pItem->dwTimes != 0xFFFFFFFF)
		{
			pItem->dwTimes--;
		}		

		if(pItem->dwTimes > 0)
		{
			if(m_pResetList == NULL)
			{
				m_pResetList = pItem;
				m_pResetList->pNext = NULL;
			}
			else
			{				
				pItem->pNext = m_pResetList;
				m_pResetList = pItem;
			}
			
			pItem = pItem->pNext;
			pItem = pTmp;
			continue;					
		}
		
		//if(bAutoRelease == true)
		//{
			//MMFree(pItem, 0);
			free(pItem);
			m_nCount--;		
		//}				

		pItem = pTmp;		
		
		m_nTimerOutCount++;		
	}	
}

6、TimerMng.h

#ifndef TIMERMNG_H
#define TIMERMNG_H

#define TVMAPI extern "C"  __declspec(dllexport) 

typedef void* HANDLE;

typedef void (* LPTIMEROUTPROC)(HANDLE hTimerVM, HANDLE hTimerItem, void* pPara);

TVMAPI HANDLE TVSysCreate(int nArraySize, time_t dtNow);
TVMAPI int TVSysDestroy(HANDLE hTimerVM);
TVMAPI HANDLE TVSetTimerCycle(HANDLE hTimerVM, time_t dtNow, unsigned int dwCycle, unsigned int nTimes, LPTIMEROUTPROC pProc, void* pPara);
TVMAPI HANDLE TVSetTimerAtTime(HANDLE hTimerVM, time_t dtNow, char* sDateTime, LPTIMEROUTPROC pProc, void* pPara);
TVMAPI void TVKillTimer(HANDLE hTimerVM, HANDLE hTimerItem);
TVMAPI size_t TVGetCount(HANDLE hTimerVM);
TVMAPI void TVCheckTimeOut(HANDLE hTimerVM, time_t dtNow);

#endif

 

7、TimerMng.cpp

 

#include "TimerVM.h"
#include "TimerMng.h"
#include <time.h>
#include <string.h>
#include <stdlib.h>

TVMAPI HANDLE TVSysCreate(int nArraySize, time_t dtNow)
{
	if(nArraySize <= 1)
	{
		return NULL;
	}

	CTimerMng* pTimerMng;
	pTimerMng = new CTimerMng;
	pTimerMng->Init(nArraySize, dtNow);
	return pTimerMng;
}

TVMAPI int TVSysDestroy(HANDLE hTimerVM)
{
	CTimerMng* pTimerMng;
	pTimerMng = (CTimerMng *)hTimerVM;
	
	pTimerMng->Destroy();
	delete pTimerMng;

	return 0;
}

TVMAPI HANDLE TVSetTimerCycle(HANDLE hTimerVM, time_t dtNow, unsigned int nElapse, unsigned int nTimes, LPTIMEROUTPROC pProc, void* pPara)
{
	CTimerMng* pTimerMng;
	pTimerMng = (CTimerMng *)hTimerVM;
	return(pTimerMng->SetTimer(dtNow, nElapse, nTimes, pProc, pPara));	
}

TVMAPI HANDLE TVSetTimerAtTime(HANDLE hTimerVM, time_t dtNow, char* sExpire, LPTIMEROUTPROC pProc, void* pPara)
{
	CTimerMng* pTimerMng;
	pTimerMng = (CTimerMng *)hTimerVM;
	
	char sPart[5];

	tm SystemTime;

	memcpy(sPart, sExpire, 4);
	sPart[4] = '\0';
	SystemTime.tm_year = atoi(sPart) - 1900;

	strncpy(sPart, sExpire + 4, 2);
	sPart[2] = '\0';
	SystemTime.tm_mon = atoi(sPart) - 1;

	strncpy(sPart, sExpire + 6, 2);
	sPart[2] = '\0';
	SystemTime.tm_mday = atoi(sPart);

	strncpy(sPart, sExpire + 8, 2);
	sPart[2] = '\0';
	SystemTime.tm_hour = atoi(sPart);

	strncpy(sPart, sExpire + 10, 2);
	sPart[2] = '\0';
	SystemTime.tm_min = atoi(sPart);

	strncpy(sPart, sExpire + 12, 2);
	sPart[2] = '\0';
	SystemTime.tm_sec = atoi(sPart);

	SystemTime.tm_isdst = 0;

	time_t dtExpire;	
	dtExpire = mktime(&SystemTime);	

	if(dtExpire <= dtNow)
	{
		return NULL;
	}

	return(pTimerMng->SetTimer(dtNow, dtExpire - dtNow, 1, pProc, pPara));		
}

TVMAPI void TVKillTimer(HANDLE hTimerVM, HANDLE hTimerItem)
{
	CTimerMng* pTimerMng;
	pTimerMng = (CTimerMng *)hTimerVM;
	pTimerMng->KillTimer((LPTIMERITEM)hTimerItem);
}

TVMAPI size_t TVGetCount(HANDLE hTimerVM)
{
	CTimerMng* pTimerMng;
	pTimerMng = (CTimerMng *)hTimerVM;
	return pTimerMng->GetCount();	
}

TVMAPI void TVCheckTimeOut(HANDLE hTimerVM, time_t dtNow)
{
	CTimerMng* pTimerMng;
	pTimerMng = (CTimerMng *)hTimerVM;
	pTimerMng->CheckTimeOut(dtNow);		
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值