TimerNoAllocator.cpp
888888888888888888888888888888888888888888888888888
#include "timer/TimerNoAllocator.h"
#include "timer/TimerConst.h"
#include "timer/ErrCode.h"
#include "timer/TimerNo.h"
#include <pthread.h>
namespace
{
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
bool timerNoWithNoParaStateTbl[MAX_DYN_TIMER_RECEIVER_ID + 1][31] = {
{false}};
}
ErrCode TimerNoAllocator::alloc(U32 receiverId, bool hasPara, U8& timerNo)
{
if (hasPara)
{
timerNo = DYN_TIMER_NO_32;
return ERR_TIMER_SUCC;
}
pthread_mutex_lock(&mutex);
bool* p = &timerNoWithNoParaStateTbl[receiverId][0];
for (U8 i = 0; i < 31; i++)
{
if (p[i] == false)
{
p[i] = true;
timerNo = DYN_TIMER_NO_1 + i;
pthread_mutex_unlock(&mutex);
return ERR_TIMER_SUCC;
}
}
pthread_mutex_unlock(&mutex);
return ERR_TIMER_ALLOC_TIMER_NO_FAILED;
}
void TimerNoAllocator::free(U32 receiverId, U8 timerNo)
{
pthread_mutex_lock(&mutex);
timerNoWithNoParaStateTbl[receiverId][timerNo - DYN_TIMER_NO_1] = false;
pthread_mutex_unlock(&mutex);
}
888888888888888888888888888888888888888888888888888888888
TimerDbg.cpp
88888888888888888888888888888888888888888888888888888
/*
* TimerDbg.cpp
*
* Created on: May 13, 2016
* Author: wlp
*/
#include "infra/util/StringUtil.h"
#include "timer/TimerCommRes.h"
#include <list>
#include <vector>
#include "log/Log.h"
std::list<std::string> getTimerOutInfoDbg(U32 workerId)
{
U32 seconds = 0;
std::list<std::string> TimersOutInfolist;
std::vector<TimerCtrlBlock*> TimersInfo;
TimerCommRes& timerCommRes = TimerCommRes::getInstance();
TimersInfo = timerCommRes.getTimersInfo(workerId);
for (std::vector<TimerCtrlBlock*>::iterator it = TimersInfo.begin();
it != TimersInfo.end(); ++it)
{
if ((*it)->hasTimeOut == TRUE)
{
clockToSeconds((*it)->timeoutClock, seconds);
TimersOutInfolist.push_back(StringUtil::toString(seconds) + "/" +
StringUtil::toString((*it)->para) + "/" +
StringUtil::toString((*it)->timerNo) + "/" +
StringUtil::toString((*it)->timerType) + "/" +
StringUtil::toString((*it)->workerId));
}
}
return TimersOutInfolist;
}
std::list<std::string> getRunningTimerInfoDbg()
{
std::list<std::string> runningTimerInfolist;
std::vector<TimerCtrlBlock*> timersInfo;
TimerCommRes& timerCommRes = TimerCommRes::getInstance();
timersInfo = timerCommRes.getRunningTimerInfo();
for (std::vector<TimerCtrlBlock*>::iterator it = timersInfo.begin();
it != timersInfo.end(); ++it)
{
runningTimerInfolist.push_back(StringUtil::toString((*it)->para) + "/" +
StringUtil::toString((*it)->timerNo) + "/" +
StringUtil::toString((*it)->timerType) + "/" +
StringUtil::toString((*it)->workerId));
}
return runningTimerInfolist;
}
void getTimerCtrBlocksDbg(U32& total, U32& usedNum, U32& unUsedNum)
{
TimerCommRes& timerCommRes = TimerCommRes::getInstance();
unUsedNum = timerCommRes.getFreeBlockNum();
total = MAX_TMCB_NUM;
usedNum = MAX_TMCB_NUM - timerCommRes.getFreeBlockNum();
}
U32 getTimerTypeDbg(U32 workerId, U8 timerNo, U32 para)
{
TimerCommRes& timerCommRes = TimerCommRes::getInstance();
TimerCtrlBlock* p = timerCommRes.getTimerCtrlBlock(workerId, timerNo, para);
if (p != nullptr) return p->timerType;
return 0xFFFFFFFF;
}
888888888888888888888888888888888888888888888888
TimerContext.cpp
888888888888888888888888888888888888888888888888888888
/*
* TimerContext.cpp
*
* Created on: 2016骞?鏈?5鏃? * Author: zxl
*/
#include "timer/TimerContext.h"
#include "timer/TimerConst.h"
TimerContext& TimerContext::getInstance()
{
static TimerContext inst;
return inst;
}
void TimerContext::inject(UserContext ctxt,
RECEIVER_CALLBACK timerOutFunc,
RECEIVER_CALLBACK deadlyChaseFunc,
GET_RECEIVE_ID_CALLBACK idFunc)
{
U8 index = static_cast<U8>(ctxt);
if (index == 0 || index > 2) return;
this->ctxt |= index;
timerOutFuncs[index] = timerOutFunc;
deadlyChaseFuncs[index] = deadlyChaseFunc;
idFuncs[index] = idFunc;
}
U8 TimerContext::getContext()
{
return ctxt;
}
RECEIVER_CALLBACK TimerContext::getTimerOutFunc(UserContext ctxt)
{
U8 index = static_cast<U8>(ctxt);
if (index == 0 || index > 2) return nullptr;
return timerOutFuncs[index];
}
RECEIVER_CALLBACK TimerContext::getDeadlyChaseFunc(UserContext ctxt)
{
U8 index = static_cast<U8>(ctxt);
if (index == 0 || index > 2) return nullptr;
return deadlyChaseFuncs[index];
}
GET_RECEIVE_ID_CALLBACK TimerContext::getIdFunc(UserContext ctxt)
{
U8 index = static_cast<U8>(ctxt);
if (index == 0 || index > 2) return nullptr;
return idFuncs[index];
}
UserContext getUserContext(U32& receiverId)
{
TimerContext& ctxt = TimerContext::getInstance();
U8 retCtxt = ctxt.getContext();
GET_RECEIVE_ID_CALLBACK idFunc;
UserContext userCtxt;
if (retCtxt == 1 || retCtxt == 2)
{
if (retCtxt == 1)
userCtxt = SaturnCtxt;
else
userCtxt = PubSubCtxt;
idFunc = ctxt.getIdFunc(static_cast<UserContext>(retCtxt));
receiverId = (*idFunc)();
}
else if (retCtxt == 3)
{
userCtxt = SaturnCtxt;
idFunc = ctxt.getIdFunc(SaturnCtxt);
receiverId = (*idFunc)();
if (receiverId == INVALID_TIMER_RECEIVER_ID)
{
userCtxt = PubSubCtxt;
idFunc = ctxt.getIdFunc(PubSubCtxt);
receiverId = (*idFunc)();
}
}
else
{
userCtxt = InvalidCtxt;
}
return userCtxt;
}
88888888888888888888888888888888888888888888888
TimerCommRes.cpp
888888888888888888888888888888888888888888888888888888888888
#include "timer/TimerCommRes.h"
#include "util/StringUtil.h"
#include "lock-free/Queue.h"
#include "timer/ErrCode.h"
#include "message/Message.h"
#include "message/MsgBrief.h"
#include "message/MsgTail.h"
#include "message/MsgOption.h"
#include "base/EventId.h"
#include "log/Log.h"
#include "infra/message/CallBackFuncDef.h"
#include "timer/TimerNoAllocator.h"
#include "timer/TimerNo.h"
#include <cstdlib>
#include <cstring>
#include <string>
#include <list>
namespace
{
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
}
TimerCommRes::TimerCommRes() : tmcb({
{0}})
{
ErrCode ret = initQueue(&queue, sizeof(U32), MAX_TMCB_NUM);
if (ret != ERR_TIMER_SUCC)
{
ERR_LOG("lock free init_queue error: %u\n", ret);
return;
}
for (U32 timerId = 0; timerId < MAX_TMCB_NUM; timerId++)
{
ret = enQueue(queue, &timerId);
if (ret != ERR_TIMER_SUCC)
{
ERR_LOG("lock free enqueue error: %u\n", ret);
return;
}
}
}
TimerCommRes::~TimerCommRes()
{
for (U32 workerId = 0; workerId < MAX_TMCB_NUM; workerId++)
{
timerGroup[workerId].timersInWorker.clear();
}
while(!isQueueEmpty(queue))
{
U32 timerId;
ErrCode ret = deQueue(queue, &timerId);
if (ret != ERR_TIMER_SUCC)
{
ERR_LOG("deQueue failed!");
}
}
}
TimerCommRes& TimerCommRes::getInstance()
{
static TimerCommRes inst;
return inst;
}
U32 TimerCommRes::allocTimerCtrlBlock(U32 workerId, U8 timerNo, U32 para)
{
if (workerId > MAX_TMCB_NUM)
return INVALID_TIMER_ID;
U32 timerId;
ErrCode ret = deQueue(queue, &timerId);
if (ret != ERR_TIMER_SUCC)
{
ERR_LOG("deQueue failed!");
return INVALID_TIMER_ID;
}
if (timerId > MAX_TMCB_NUM)
return INVALID_TIMER_ID;
pthread_mutex_lock(&mutex);
std::string key = StringUtil::toString(timerNo) + "/" + StringUtil::toString(para);
timerGroup[workerId].timersInWorker.insert(make_pair(key, timerId));
pthread_mutex_unlock(&mutex);
return timerId;
}
TimerCtrlBlock* TimerCommRes::getTimerCtrlBlock(U32 timerId)
{
if (timerId > MAX_TMCB_NUM) return nullptr;
return &tmcb[timerId];
}
TimerCtrlBlock* TimerCommRes::getTimerCtrlBlock(U32 workerId, U8 timerNo, U32 para)
{
if (workerId > MAX_TMCB_NUM)
return nullptr;
std::string key = StringUtil::toString(timerNo) + "/" + StringUtil::toString(para);
pthread_mutex_lock(&mutex);
if (timerGroup[workerId].timersInWorker.find(key) == timerGroup[workerId].timersInWorker.end())
{
pthread_mutex_unlock(&mutex);
return nullptr;
}
U32 timerId = timerGroup[workerId].timersInWorker[key];
pthread_mutex_unlock(&mutex);
if (timerId > MAX_TMCB_NUM)
return nullptr;
return &tmcb[timerId];
}
void TimerCommRes::freeTimerCtrlBlock(U32 timerId)
{
if (timerId > MAX_TMCB_NUM) return;
TimerCtrlBlock* p = &tmcb[timerId];
if ((p->timerNo >= DYN_TIMER_NO_1) && (p->timerNo <= DYN_TIMER_NO_31))
{
TimerNoAllocator::free(p->workerId, p->timerNo);
}
std::string key = StringUtil::toString(p->timerNo) + "/" + StringUtil::toString(p->para);
pthread_mutex_lock(&mutex);
if (p->workerId < MAX_TMCB_NUM)
{
std::map<std::string, U32>::iterator it = timerGroup[p->workerId].timersInWorker.find(key);
if (it == timerGroup[p->workerId].timersInWorker.end())
{
pthread_mutex_unlock(&mutex);
return;
}
timerGroup[p->workerId].timersInWorker.erase(key);
}
pthread_mutex_unlock(&mutex);
if(!p->hasTimeOut)
{
memset(p, 0, sizeof(TimerCtrlBlock));
}
ErrCode ret = enQueue(queue, &timerId);
if (ret != ERR_TIMER_SUCC)
{
ERR_LOG("enQueue failed!");
}
}
void sendTimeoutMsgToWorker(U32 msgId, U32 workerId, U32 para, UserContext userCtxt)
{
U32 dataLen = 0;
if (para != INVALID_PARA)
{
dataLen = sizeof(para);
}
U32 headLen = sizeof(Head);
Tail tail = {0};
U32 tailLen = sizeof(tail.length) + tail.length;
MsgOption msgOption = {0};
U32 optionLen = sizeof(msgOption.length) + msgOption.length;
U32 len = headLen + dataLen + tailLen + optionLen;
Message* msg = (Message*)calloc(1, len);
msg->msgHead.msgId = msgId;
msg->msgHead.length = dataLen;
msg->msgHead.priority = HIGH_PRIORITY;
if (dataLen > 0)
memcpy(msg->data, ¶, sizeof(para));
MsgOption * Option = (MsgOption*)((U8*)msg + headLen + dataLen + tailLen);
Option->length = 0;
TimerContext& ctxt = TimerContext::getInstance();
RECEIVER_CALLBACK callBack = ctxt.getTimerOutFunc(userCtxt);
if (callBack != nullptr) (*callBack)(workerId, msg);
free(msg);
}
void deadlyChaseTimer(U32 workerId, U8 timerNo, U32 para, UserContext userCtxt)
{
INFO_LOG("This timer: workerId %d , timerNo %d has timeout!\n", workerId, timerNo);
U32 dataLen = 0;
if (para != INVALID_PARA)
{
dataLen = sizeof(para);
}
U32 headLen = sizeof(Head);
Tail tail = {0};
U32 tailLen = sizeof(tail.length) + tail.length;
MsgOption msgOption = {0};
U32 optionLen = sizeof(msgOption.length) + msgOption.length;
U32 len = headLen + dataLen + tailLen + optionLen;
Message* msg = (Message*)calloc(1, len);
msg->msgHead.msgId = EV_TIMER_BEGIN + timerNo;
msg->msgHead.priority = HIGH_PRIORITY;
msg->msgHead.length = dataLen;
if (dataLen > 0)
memcpy(msg->data, ¶, sizeof(para));
MsgOption * Option = (MsgOption*)((U8*)msg + headLen + dataLen + tailLen);
Option->length = 0;
TimerContext& ctxt = TimerContext::getInstance();
RECEIVER_CALLBACK callBack = ctxt.getDeadlyChaseFunc(userCtxt);
if (callBack != nullptr) (*callBack)(workerId, msg);
free(msg);
}
U32 TimerCommRes::getFreeBlockNum()
{
return getQueueSize(queue);
}
std::vector<TimerCtrlBlock*> TimerCommRes::getTimersInfo(U32 workerId)
{
std::vector<TimerCtrlBlock*> timersInfo;
if (workerId > MAX_TMCB_NUM)
{
ERR_LOG("get workerId fail !");
return timersInfo;
}
for (U32 timerId = 0; timerId < MAX_TMCB_NUM; timerId++)
{
if(workerId == tmcb[timerId].workerId)
{
timersInfo.push_back(&tmcb[timerId]);
}
}
return timersInfo;
}
std::vector<TimerCtrlBlock*> TimerCommRes::getRunningTimerInfo()
{
std::vector<TimerCtrlBlock*> runningTimerInfo;
for (U32 i = 0; i < MAX_TMCB_NUM; i++)
{
if ((InvalidCtxt != tmcb[i].userCtxt) && (TRUE != tmcb[i].hasTimeOut))
{
runningTimerInfo.push_back(&tmcb[i]);
}
}
return runningTimerInfo;
}
88888888888888888888888888888888888888888888888888888888888888888
TimerAgt.cpp
8888888888888888888888888888888888888888888888888888888888888888
#include "timer/TimerAgt.h"
#include "timer/AbsTimer.h"
#include "timer/RelativeTimer.h"
#include "timer/TimerCommRes.h"
#include "timer/ErrCode.h"
#include "timer/Clock.h"
#include "timer/TimerContext.h"
#include "log/Log.h"
ErrCode startTimer(U8 timerNo, U32 timerLen, U32 para)
{
if (timerNo == 0 || timerNo > MAX_WORKER_TIMER_NUM) return ERR_TIMER_INVALID_TIMER_NO;
U32 receiverId;
UserContext userCtxt = getUserContext(receiverId);
if (userCtxt == InvalidCtxt) return ERR_TIMER_INVALID_CTXT;
if ((receiverId >= MAX_TMCB_NUM)||(receiverId == INVALID_TIMER_RECEIVER_ID)) return ERR_TIMER_INVALID_WORKER_ID;
if (setRelativeTimer(receiverId, timerNo, timerLen, para, userCtxt) == INVALID_TIMER_ID)
return ERR_TIMER_ALLOC_TIMER_ID_FAILED;
return ERR_TIMER_SUCC;
}
ErrCode startTimer(U8 timerNo, SysSoftClock& clock)
{
if (timerNo == 0 || timerNo > MAX_WORKER_TIMER_NUM) return ERR_TIMER_INVALID_TIMER_NO;
U32 receiverId;
UserContext userCtxt = getUserContext(receiverId);
if (userCtxt == InvalidCtxt) return ERR_TIMER_INVALID_CTXT;
if ((receiverId >= MAX_TMCB_NUM)||(receiverId == INVALID_TIMER_RECEIVER_ID)) return ERR_TIMER_INVALID_WORKER_ID;
U32 timerLen = 0;
clockToSeconds(clock, timerLen);
if (setAbsTimer(receiverId, timerNo, timerLen, userCtxt) == INVALID_TIMER_ID)
return ERR_TIMER_ALLOC_TIMER_ID_FAILED;
return ERR_TIMER_SUCC;
}
void stopTimer(U8 timerNo, U32 para)
{
if (timerNo == 0 || timerNo > MAX_WORKER_TIMER_NUM) return;
U32 receiverId;
UserContext userCtxt = getUserContext(receiverId);
if (userCtxt == InvalidCtxt) return;
if ((receiverId >= MAX_TMCB_NUM)||(receiverId == INVALID_TIMER_RECEIVER_ID)) return;
TimerCommRes& timerCommRes = TimerCommRes::getInstance();
TimerCtrlBlock* p = timerCommRes.getTimerCtrlBlock(receiverId, timerNo, para);
if (p == nullptr)
{
ERR_LOG("can not stop: This timer timerNo %d, receiverId:%d does not exist!", timerNo, receiverId);
return;
}
if(p->timerType == ABS_TYPE)
{
killAbsTimer(timerNo, receiverId);
}
else
{
killRelativeTimer(receiverId, timerNo, para);
}
}
88888888888888888888888888888888888888888888888888888888888888888
ScanTimer.cpp
8888888888888888888888888888888888888888888888888888888888888888888
#ifndef HBAF45D63_D6D5_4CBD_A2F9_724AF16DB2E7
#define HBAF45D63_D6D5_4CBD_A2F9_724AF16DB2E7
#include "timer/ScanTimer.h"
#include "timer/TimerConst.h"
#include "timer/RelativeTimer.h"
#include "timer/AbsTimer.h"
#include "log/Log.h"
#include "sys/time.h"
#include <sched.h>
#include <unistd.h>
namespace
{
pthread_t notifier;
pthread_t waiter;
pthread_mutex_t lock;
pthread_cond_t scanable;
U32 count = 0;
U32 m = 0;
U32 n = 0;
U32 k = 0;
U32 j = 0;
struct timeval time1 = {0};
struct timeval time2 = {0};
struct timeval timeDiff = {0};
}
void initScanTimer()
{
pthread_mutex_init(&lock, NULL);
pthread_cond_init(&scanable, NULL);
pthread_attr_t attr = getThreadAttr();
int ret = pthread_create(¬ifier, &attr, notifyRoutine, NULL);
if (ret != 0) ERR_LOG("create thread fail\n");
ret = pthread_create(&waiter, &attr, waitRoutine, NULL);
if (ret != 0) ERR_LOG("create thread fail\n");
}
pthread_attr_t getThreadAttr()
{
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
pthread_attr_setschedpolicy(&attr,SCHED_BATCH);
struct sched_param param;
param.sched_priority = sched_get_priority_max(PTHREAD_EXPLICIT_SCHED);
pthread_attr_setschedparam(&attr, ¶m);
return attr;
}
void* notifyRoutine(void* para)
{
while (TRUE)
{
usleep(1000);
pthread_cond_signal(&scanable);
}
return NULL;
}
void* waitRoutine(void* para)
{
while (TRUE)
{
pthread_cond_wait(&scanable, &lock);
scanTimer();
}
return NULL;
}
void scanTimer()
{
static struct timeval time1 = {0};
static struct timeval time2 = {0};
if (k == 0)
{
gettimeofday(&time1, NULL);
k++;
}
m++;
n = 1;
#if 1
if (m == 5)
{
static U32 timeDiff = 0;
gettimeofday(&time2, NULL);
timeDiff += (time2.tv_sec - time1.tv_sec) * 1000000 + time2.tv_usec - time1.tv_usec;
time1 = time2;
n = timeDiff / 1000 + 1;
//INFO_LOG("timeDiff: %d, n: %d", timeDiff, n);
if (n > 5) n -= 5;
timeDiff = timeDiff % 1000;
m = 0;
}
#endif
j += n;
//if (j % 1000 == 0) INFO_LOG("j : %d, n: %d", j, n);
for (U32 i = 0; i < n; i++)
{
scanRelativeTimer();
count++;
if (count == 1000)
{
scanAbsTimer();
count = 0;
}
}
}
#endif
888888888888888888888888888888888888888888888888888888888888888888888888888
RelativeTimer.cpp
8888888888888888888888888888888888888888888888888888888888888
#include "timer/RelativeTimer.h"
#include "timer/TimerCommRes.h"
#include "base/EventId.h"
#include "log/Log.h"
#include "timer/TimerNo.h"
#include <pthread.h>
#include <string.h>
namespace
{
typedef enum QueueType
{
TICK_TYPE,
TID_TYPE
} QueueType;
struct RelativeCtrlBlock
{
U32 originalCount;
U32 count;
QueueType queueType;
Node* node;
U32 tickIndex;
};
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
RelativeCtrlBlock rcb[MAX_TMCB_NUM] = {0};
RelativeTimerQueue rtq = {0};
void addRelativeTimer(U32 timerId)
{
if (rcb[timerId].originalCount > MAX_TMCB_NUM)
{
rcb[timerId].queueType = TID_TYPE;
rtq.tid[timerId] = TIMER_IN_TID_LIST;
if (timerId > rtq.cursorForTid)
rcb[timerId].count = rcb[timerId].originalCount + MAX_TMCB_NUM - (timerId - rtq.cursorForTid);
else
rcb[timerId].count = rcb[timerId].originalCount + rtq.cursorForTid - timerId;
}
else
{
rcb[timerId].queueType = TICK_TYPE;
rcb[timerId].tickIndex = (rcb[timerId].originalCount + rtq.cursorForTick) % MAX_TMCB_NUM;
Elem elem;
elem.v = timerId;
rcb[timerId].node = insertElem(rtq.tick[rcb[timerId].tickIndex], elem);
}
rtq.elemCount++;
}
void setTimerCtrlBlock(U32 workerId, U8 timerNo, U32 timerLen, U32 para, U32 timerId, UserContext userCtxt)
{
U32 tickSum = (timerLen / 10) * 10;
if (timerLen % 10 != 0) tickSum += 10;
TimerCommRes& timerCommRes = TimerCommRes::getInstance();
TimerCtrlBlock* p = timerCommRes.getTimerCtrlBlock(timerId);
memset(p, 0, sizeof(TimerCtrlBlock));
p->timerType = RELATIVE_TYPE;
p->workerId = workerId;
p->timerNo = timerNo;
p->para = para;
p->timerId = timerId;
p->userCtxt = userCtxt;
rcb[timerId].originalCount = tickSum;
}
}
void initRelativeTimer()
{
for (U32 timerId = 0; timerId < MAX_TMCB_NUM; timerId++)
{
rtq.tick[timerId] = initList(ValueType);
}
}
U32 setRelativeTimer(U32 workerId, U8 timerNo, U32 timerLen, U32 para, UserContext userCtxt)
{
pthread_mutex_lock(&mutex);
TimerCommRes& timerCommRes = TimerCommRes::getInstance();
TimerCtrlBlock* p = timerCommRes.getTimerCtrlBlock(workerId, timerNo, para);
if (p != nullptr)
{
if (p->timerType == ABS_TYPE)
{
ERR_LOG("can not set relative timer : same workerId and timerNo as a ABS_TYPE");
pthread_mutex_unlock(&mutex);
return INVALID_TIMER_ID;
}
killRelativeTimer(workerId, timerNo, para);
}
U32 timerId = timerCommRes.allocTimerCtrlBlock(workerId, timerNo, para);
if (timerId == INVALID_TIMER_ID)
{
pthread_mutex_unlock(&mutex);
return INVALID_TIMER_ID;
}
setTimerCtrlBlock(workerId, timerNo, timerLen, para, timerId, userCtxt);
addRelativeTimer(timerId);
pthread_mutex_unlock(&mutex);
return timerId;
}
void killRelativeTimer(U32 workerId, U8 timerNo, U32 para)
{
TimerCommRes& timerCommRes = TimerCommRes::getInstance();
TimerCtrlBlock* p = timerCommRes.getTimerCtrlBlock(workerId, timerNo, para);
if (p == nullptr) return;
if (p->hasTimeOut)
{
deadlyChaseTimer(workerId, p->timerNo, p->para, p->userCtxt);
return;
}
if (rcb[p->timerId].queueType == TID_TYPE)
{
rtq.tid[p->timerId] = 0;
}
else
{
Node* node = rcb[p->timerId].node;
deleteNode(rtq.tick[rcb[p->timerId].tickIndex], node);
}
rtq.elemCount--;
timerCommRes.freeTimerCtrlBlock(p->timerId);
}
void scanTickQueue()
{
rtq.cursorForTick = (rtq.cursorForTick + 1) % MAX_TMCB_NUM;
List* list = rtq.tick[rtq.cursorForTick];
TimerCommRes& timerCommRes = TimerCommRes::getInstance();
U32 timerId = fetchElemFromHead(list).v;
SysSoftClock timeOutClock = {0};
while (timerId != LIST_HAS_EMPTY)
{
TimerCtrlBlock* p = timerCommRes.getTimerCtrlBlock(timerId);
U8 timerNo = p->timerNo;
/* timerNo: 0, SynUnblockedWorker use */
if (timerNo >= 0 && timerNo <= TIMER_NO_END)
{
U32 msgId = EV_TIMER_BEGIN + timerNo;
U32 workerId = p->workerId;
U32 para = p->para;
if (workerId < MAX_TMCB_NUM)
{
getCurrentSysSoftClock(timeOutClock);
memcpy(&(p->timeoutClock), &timeOutClock, sizeof(p->timeoutClock));
sendTimeoutMsgToWorker(msgId, workerId, para, p->userCtxt);
p->hasTimeOut = TRUE;
}
}
timerCommRes.freeTimerCtrlBlock(timerId);
rtq.elemCount--;
timerId = fetchElemFromHead(list).v;
}
}
void scanTidQueue()
{
rtq.cursorForTid = (rtq.cursorForTid + 1) % MAX_TMCB_NUM;
if (rtq.tid[rtq.cursorForTid] == TIMER_IN_TID_LIST)
{
TimerCommRes& timerCommRes = TimerCommRes::getInstance();
TimerCtrlBlock* p = timerCommRes.getTimerCtrlBlock(rtq.cursorForTid);
rcb[rtq.cursorForTid].count -= MAX_TMCB_NUM;
Elem elem;
elem.v = rtq.cursorForTid;
if (rcb[rtq.cursorForTid].count <= MAX_TMCB_NUM)
{
rcb[rtq.cursorForTid].queueType = TICK_TYPE;
rcb[rtq.cursorForTid].tickIndex = (rcb[rtq.cursorForTid].count + rtq.cursorForTick) % MAX_TMCB_NUM;
rcb[rtq.cursorForTid].node = insertElem(rtq.tick[rcb[rtq.cursorForTid].tickIndex], elem);
}
}
}
void scanRelativeTimer()
{
pthread_mutex_lock(&mutex);
scanTickQueue();
scanTidQueue();
pthread_mutex_unlock(&mutex);
}
8888888888888888888888888888888888888888888888888888888888888888
Init.cpp
8888888888888888888888888888888888888888888888888888888888888
/*
* Init.cpp
*
* Created on: 2016骞?鏈?7鏃? * Author: yyy
*/
#include "timer/Init.h"
#include "timer/RelativeTimer.h"
#include "timer/ScanTimer.h"
void initTimer()
{
initRelativeTimer();
initScanTimer();
}
InitializationCtrl& InitializationCtrl::getInstance()
{
static InitializationCtrl inst;
return inst;
}
bool InitializationCtrl::hasDone()
{
return flag;
}
void InitializationCtrl::setFlag()
{
flag = true;
}
888888888888888888888888888888888888888888888888888888888888888888888
DynTimerAgt.cpp
88888888888888888888888888888888888888888888888
#include "timer/DynTimerAgt.h"
#include "timer/AbsTimer.h"
#include "timer/RelativeTimer.h"
#include "timer/TimerCommRes.h"
#include "timer/ErrCode.h"
#include "timer/Clock.h"
#include "timer/TimerContext.h"
#include "timer/TimerNoAllocator.h"
#include "infra/log/Log.h"
#include "base/EventId.h"
namespace TimerAgt
{
ErrCode startDynTimer(U32 timerLen, U32 para, U32& event)
{
U32 receiverId;
UserContext userCtxt = getUserContext(receiverId);
if (userCtxt == InvalidCtxt) return ERR_TIMER_INVALID_CTXT;
if ((receiverId >= MAX_DYN_TIMER_RECEIVER_ID)||(receiverId == INVALID_TIMER_RECEIVER_ID))
return ERR_TIMER_INVALID_WORKER_ID;
U8 timerNo;
if (TimerNoAllocator::alloc(receiverId, para != INVALID_PARA, timerNo) != ERR_TIMER_SUCC)
return ERR_TIMER_ALLOC_TIMER_NO_FAILED;
if (setRelativeTimer(receiverId, timerNo, timerLen, para, userCtxt) == INVALID_TIMER_ID)
return ERR_TIMER_ALLOC_TIMER_ID_FAILED;
event = EV_TIMER_BEGIN + timerNo;
return ERR_TIMER_SUCC;
}
ErrCode startDynTimer(SysSoftClock& clock, U32& event)
{
U32 receiverId;
UserContext userCtxt = getUserContext(receiverId);
if (userCtxt == InvalidCtxt) return ERR_TIMER_INVALID_CTXT;
if ((receiverId >= MAX_TMCB_NUM)||(receiverId == INVALID_TIMER_RECEIVER_ID))
return ERR_TIMER_INVALID_WORKER_ID;
U32 timerLen = 0;
clockToSeconds(clock, timerLen);
U8 timerNo;
if (TimerNoAllocator::alloc(receiverId, false, timerNo) != ERR_TIMER_SUCC)
return ERR_TIMER_ALLOC_TIMER_NO_FAILED;
if (setAbsTimer(receiverId, timerNo, timerLen, userCtxt) == INVALID_TIMER_ID)
return ERR_TIMER_ALLOC_TIMER_ID_FAILED;
event = EV_TIMER_BEGIN + timerNo;
return ERR_TIMER_SUCC;
}
void stopDynTimer(U32 event, U32 para)
{
U32 receiverId;
UserContext userCtxt = getUserContext(receiverId);
if (userCtxt == InvalidCtxt) return;
if ((receiverId > MAX_DYN_TIMER_RECEIVER_ID)||(receiverId == INVALID_TIMER_RECEIVER_ID)) return;
TimerCommRes& timerCommRes = TimerCommRes::getInstance();
U8 timerNo = event - EV_TIMER_BEGIN;
TimerCtrlBlock* p = timerCommRes.getTimerCtrlBlock(receiverId, timerNo, para);
if (p == nullptr)
{
ERR_LOG("can not stop: This timer timerNo %u, receiverId %d does not exist!", timerNo, receiverId);
return;
}
if(p->timerType == ABS_TYPE)
{
killAbsTimer(p->timerNo, receiverId);
}
else
{
killRelativeTimer(receiverId, p->timerNo, p->para);
}
}
}
Event startDynTimer(U32 timerLen, U32 para)
{
Event event = INVALID_EVENT;
ErrCode ret = TimerAgt::startDynTimer(timerLen, para, event);
if (ret != ERR_TIMER_SUCC)
{
ERR_LOG("start dyn relative timer failed, errcode is %u", ret);
return INVALID_EVENT;
}
return event;
}
Event startDynTimer(SysSoftClock& clock)
{
Event event = INVALID_EVENT;
ErrCode ret = TimerAgt::startDynTimer(clock, event);
if (ret != ERR_TIMER_SUCC)
{
ERR_LOG("start dyn abs timer failed, errcode is %u", ret);
return INVALID_EVENT;
}
return event;
}
void stopDynTimer(Event event, U32 para)
{
if (event < EV_DYN_TIMER_1 || event > EV_DYN_TIMER_32)
{
ERR_LOG("invalid timer event, event is %u", event);
return;
}
TimerAgt::stopDynTimer(event, para);
}
88888888888888888888888888888888888888888888888888888888888888888
Clock.cpp
888888888888888888888888888888888888888888888888888888888888888888888
/*
* Clock.cpp
*
* Created on: 2016骞?鏈?7鏃? * Author:yyy
*/
#include "timer/TimerConst.h"
#include "timer/ErrCode.h"
#include "timer/Clock.h"
#include "log/Log.h"
#include <sys/time.h>
#include <time.h>
#include <cstdlib>
#include <cstring>
namespace
{
const U32 INVALID_SECONDS_VALUE = 0xFFFFFFFF;
}
void getCurrentSysSoftClock(SysSoftClock& clock)
{
struct timeval sysTime = {0};
gettimeofday(&sysTime, nullptr);
clock.count10ms = (U8)(sysTime.tv_usec / 10000);
struct tm tmpTime = {0};
localtime_r(&sysTime.tv_sec, &tmpTime);
clock.year = (U16)(tmpTime.tm_year + 1900);
clock.month = (U8)(tmpTime.tm_mon + 1);
clock.day = (U8)tmpTime.tm_mday;
clock.hour = (U8)tmpTime.tm_hour;
clock.minute = (U8)tmpTime.tm_min;
clock.second = (U8)tmpTime.tm_sec;
clock.week = (U8)tmpTime.tm_wday;
}
ErrCode clockToSeconds(SysSoftClock& clock, U32& seconds)
{
struct tm tm_clock;
tm_clock.tm_year = 1999 - 1900;
tm_clock.tm_mon = 0;
tm_clock.tm_mday = 1;
tm_clock.tm_hour = 0;
tm_clock.tm_min = 0;
tm_clock.tm_sec = 0;
tm_clock.tm_isdst = 0;
time_t t = mktime(&tm_clock);
if (t == INVALID_SECONDS_VALUE)
{
return ERR_TIMER_CALL_MKTIME_FAIL;
}
tm_clock.tm_year = clock.year - 1900;
tm_clock.tm_mon = clock.month - 1;
tm_clock.tm_mday = clock.day;
tm_clock.tm_hour = clock.hour;
tm_clock.tm_min = clock.minute;
tm_clock.tm_sec = clock.second;
tm_clock.tm_isdst = 0;
time_t t1 = mktime(&tm_clock);
if (t1 == INVALID_SECONDS_VALUE)
{
return ERR_TIMER_CALL_MKTIME_FAIL;
}
if (t1 < t)
{
return ERR_TIMER_INPUT_CLOCK_TOO_EARLY;
}
else
{
seconds = t1 - t;
return ERR_TIMER_SUCC;
}
}
ErrCode secondsToClock(U32 seconds, SysSoftClock& clock)
{
struct tm tm_clock;
tm_clock.tm_year = 1999 - 1900;
tm_clock.tm_mon = 0;
tm_clock.tm_mday = 1;
tm_clock.tm_hour = 0;
tm_clock.tm_min = 0;
tm_clock.tm_sec = 0;
tm_clock.tm_isdst = 0;
time_t t = mktime(&tm_clock);
if (t == INVALID_SECONDS_VALUE)
{
return ERR_TIMER_CALL_MKTIME_FAIL;
}
t = t + seconds;
struct tm* time = localtime_r(&t, &tm_clock);
if (time == nullptr)
{
return ERR_TIMER_CALL_LOCALTIME_FAIL;
}
clock.second = (U8)time->tm_sec;
clock.minute = (U8)time->tm_min;
clock.hour = (U8)time->tm_hour;
clock.day = (U8)time->tm_mday;
clock.month = (U8)(time->tm_mon + 1);
clock.year = (U16)(time->tm_year + 1900);
clock.week = (U8)(0 == time->tm_wday ? 7 : time->tm_wday);
clock.count10ms = 0;
return ERR_TIMER_SUCC;
}
8888888888888888888888888888888888888888888888888888888888888
AbsTimer.cpp
888888888888888888888888888888888888888888888888888888888888
/*
* AbsTimer.cpp
*
* Created on: 2016锟?锟?5锟? * Author:yyy
*/
#include "timer/AbsTimer.h"
#include "timer/TimerConst.h"
#include "timer/ErrCode.h"
#include "timer/TimerNo.h"
#include "timer/Clock.h"
#include "base/EventId.h"
#include "timer/TimerCommRes.h"
#include "log/Log.h"
#include <pthread.h>
#include <cstdlib>
#include <cstring>
namespace
{
struct AbsCtrlBlock
{
U32 count;
U32 prev;
U32 next;
};
struct AbsTimerQueue
{
U32 head;
U32 tail;
U32 elemCount;
} ;
AbsCtrlBlock acb[MAX_TMCB_NUM] = {0};
AbsTimerQueue absTimerQueue = {INVALID_TIMER_ID, INVALID_TIMER_ID, 0};
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void addAbsTimerQueue(U32 timerId)
{
WARN_LOG("addAbsTmcb: %u", timerId);
pthread_mutex_lock(&mutex);
if ((absTimerQueue.head == INVALID_TIMER_ID) && (absTimerQueue.tail == INVALID_TIMER_ID))
{
absTimerQueue.head = timerId;
absTimerQueue.tail = absTimerQueue.head;
acb[timerId].next = INVALID_TIMER_ID;
acb[timerId].prev = INVALID_TIMER_ID;
}
else
{
U32 current = absTimerQueue.head;
while (true)
{
if (acb[timerId].count <= acb[current].count)
{
acb[timerId].next = current;
acb[timerId].prev = acb[current].prev;
if (acb[current].prev != INVALID_TIMER_ID) acb[acb[current].prev].next = timerId;
acb[current].prev = timerId;
if (current == absTimerQueue.head) absTimerQueue.head = timerId;
break;
}
else
{
current = acb[current].next;
if (current == INVALID_TIMER_ID)
{
acb[absTimerQueue.tail].next = timerId;
acb[timerId].prev = absTimerQueue.tail;
acb[timerId].next = INVALID_TIMER_ID;
absTimerQueue.tail = timerId;
break;
}
}
}
}
absTimerQueue.elemCount++;
pthread_mutex_unlock(&mutex);
}
void removeAcb(U32 timerId)
{
WARN_LOG("removeTmcb: %u", timerId);
if (timerId > MAX_TMCB_NUM) return;
if (timerId == absTimerQueue.head && timerId == absTimerQueue.tail)
{
absTimerQueue.head = INVALID_TIMER_ID;
absTimerQueue.tail = INVALID_TIMER_ID;
}
else if (timerId == absTimerQueue.head)
{
acb[acb[timerId].next].prev = INVALID_TIMER_ID;
absTimerQueue.head = acb[timerId].next;
acb[timerId].next = INVALID_TIMER_ID;
}
else if (timerId == absTimerQueue.tail)
{
acb[acb[timerId].prev].next = INVALID_TIMER_ID;
absTimerQueue.tail = acb[timerId].prev;
acb[timerId].prev = INVALID_TIMER_ID;
}
else
{
acb[acb[timerId].prev].next = acb[timerId].next;
acb[acb[timerId].next].prev = acb[timerId].prev;
acb[timerId].prev = INVALID_TIMER_ID;
acb[timerId].next = INVALID_TIMER_ID;
}
}
void setTimerCtrlBlock(U32 workerId, U8 timerNo, U32 timerLen, U32 timerId, UserContext userCtxt)
{
TimerCommRes& timerCommRes = TimerCommRes::getInstance();
TimerCtrlBlock* p = timerCommRes.getTimerCtrlBlock(timerId);
memset(p, 0, sizeof(TimerCtrlBlock));
p->timerType = ABS_TYPE;
p->workerId = workerId;
p->timerNo = timerNo;
p->para = INVALID_PARA;
p->timerId = timerId;
p->userCtxt = userCtxt;
acb[timerId].count = timerLen;
}
}
U32 setAbsTimer(U32 workerId, U8 timerNo, U32 timerLen, UserContext userCtxt)
{
TimerCommRes& timerCommRes = TimerCommRes::getInstance();
TimerCtrlBlock* p = timerCommRes.getTimerCtrlBlock(workerId, timerNo, INVALID_PARA);
if (p != nullptr)
{
if (p->timerType == RELATIVE_TYPE)
{
ERR_LOG("can not set abs timer : same workerId and timerNo as a RELATIVE_TYPE");
return INVALID_TIMER_ID;
}
killAbsTimer(timerNo, workerId);
}
U32 timerId = timerCommRes.allocTimerCtrlBlock(workerId, timerNo, INVALID_PARA);
if (timerId == INVALID_TIMER_ID) return INVALID_TIMER_ID;
setTimerCtrlBlock(workerId, timerNo, timerLen, timerId, userCtxt);
addAbsTimerQueue(timerId);
INFO_LOG("set abs timer workerId: %d, timerNo: %d, timerId: %d success", workerId, timerNo, timerId);
return timerId;
}
void killAbsTimer(U32 timerNo, U32 workerId)
{
TimerCommRes& timerCommRes = TimerCommRes::getInstance();
TimerCtrlBlock* p = timerCommRes.getTimerCtrlBlock(workerId, timerNo, INVALID_PARA);
if (p == nullptr)
{
ERR_LOG("get TMCB fail !");
return;
}
if (p->hasTimeOut)
{
deadlyChaseTimer(workerId, p->timerNo, p->para, p->userCtxt);
return;
}
pthread_mutex_lock(&mutex);
removeAcb(p->timerId);
timerCommRes.freeTimerCtrlBlock(p->timerId);
absTimerQueue.elemCount--;
pthread_mutex_unlock(&mutex);
}
void scanAbsTimer()
{
SysSoftClock clock = {0};
SysSoftClock timeOutClock = {0};
getCurrentSysSoftClock(clock);
U32 seconds = 0;
clockToSeconds(clock, seconds);
pthread_mutex_lock(&mutex);
if(absTimerQueue.head == INVALID_TIMER_ID)
{
pthread_mutex_unlock(&mutex);
return;
}
TimerCommRes& timerCommRes = TimerCommRes::getInstance();
TimerCtrlBlock* first = timerCommRes.getTimerCtrlBlock(absTimerQueue.head);
if (first == nullptr)
{
pthread_mutex_unlock(&mutex);
return;
}
while (seconds >= acb[first->timerId].count)
{
if (first->timerNo > 0 && first->timerNo <= TIMER_NO_END)
{
U32 msgId = EV_TIMER_BEGIN + first->timerNo;
U32 workerId = first->workerId;
U32 para = first->para;
if (workerId < MAX_TMCB_NUM)
{
getCurrentSysSoftClock(timeOutClock);
memcpy(&(first->timeoutClock), &timeOutClock, sizeof(first->timeoutClock));
sendTimeoutMsgToWorker(msgId, workerId, para, first->userCtxt);
first->hasTimeOut = TRUE;
}
}
TimerCommRes& timerCommRes = TimerCommRes::getInstance();
removeAcb(first->timerId);
timerCommRes.freeTimerCtrlBlock(first->timerId);
absTimerQueue.elemCount--;
first = timerCommRes.getTimerCtrlBlock(absTimerQueue.head);
if (first == nullptr)
{
pthread_mutex_unlock(&mutex);
return;
}
}
pthread_mutex_unlock(&mutex);
}
8888888888888888888888888888888888888888888888888888888888888