文档章节

部分timer->cpp代码

文刀人韦
 文刀人韦
发布于 2017/08/07 13:35
字数 3130
阅读 20
收藏 0

 

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, &para, 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, &para, 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(&notifier, &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, &param);
    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

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

© 著作权归作者所有

下一篇: 部分timer代码->h
文刀人韦
粉丝 0
博文 35
码字总数 79740
作品 0
渭南
私信 提问
VS2010/MFC编程入门教程之目录和总结(鸡啄米)

鸡啄米的这套VS2010/MFC编程入门教程到此就全部完成了,虽然有些内容还未涉及到,但帮助大家进行VS2010/MFC的入门学习业已足够。以此教程的知识为基础,学习VS2010/MFC较为深入的内容已非难事...

weixin_40647819
2018/05/23
0
0
Linux C++、Boost、ACE ......

Linux/UNIX、C++、Boost、ACE、Shell ...... Linux/UNIX C++高级培训---远程班 * 培养目标:Linux/UNIX C++高级软件工程师 专注Linux/UNIX服务器端的软件开发(后台开发),培养企业所需的专...

athxy
2010/04/01
756
1
Linux c++

Linux/UNIX、C++、Boost、ACE... * 培养目标:Linux/UNIX C++高级软件工程师 专注Linux/UNIX服务器端的软件开发(后台开发),培养企业所需的专业Linux/UNIX C++高级软件工程师。 课程涉及服...

athxy
2010/06/06
4.4K
5
【Android休眠】之PowerKey唤醒源实现

http://blog.csdn.net/u013686019/article/details/53677531

menghuanbeike
2018/04/23
0
0
VM技术(二)从CHIP8入手CPU的模拟(一)

CHIP8的话网上已经有许多的模拟器的解说了,这里我们就给出CPU的模拟过程 CHIP8代码 CHIP8 CPU https://gitee.com/Luciferearth/EasyVGM/blob/master/modules/CHIP8/显示器 https://gitee.co...

Pulsar-V
07/31
22
0

没有更多内容

加载失败,请刷新页面

加载更多

从0开始学FreeRTOS-(列表&列表项)-6

FreeRTOS列表&列表项的源码解读 第一次看列表与列表项的时候,感觉很像是链表,虽然我自己的链表也不太会,但是就是感觉很像。 在FreeRTOS中,列表与列表项使用得非常多,是FreeRTOS的一个数...

杰杰1号
23分钟前
4
0
Java的23种设计模式,详细讲解(一)

一、概述 设计模式是解决问题的方案,学习现有的设计模式可以做到经验复用。 拥有设计模式词汇,在沟通时就能用更少的词汇来讨论,并且不需要了解底层细节。 二、创建型 1. 单例(Singleton...

李红欧巴
39分钟前
5
0
android 使用asynctask结合fragment更新UI(另附线程池管理示例)

https://blog.csdn.net/qq_16064871/article/details/70767949

shzwork
39分钟前
3
0
SpringCloud实现分库分表模式下,数据库实时扩容方案

本文源码:GitHub·点这里 || GitEE·点这里 一、项目结构 1、工程结构 2、模块命名 shard-common-entity: 公共代码块shard-open-inte: 开放接口管理shard-eureka-7001: ...

知了一笑
40分钟前
5
0
js--时间切割装换工具类

<!DOCTYPE html><html><head> <meta charset="UTF-8"> <title></title> <script type="text/javascript"> /* * 修改data原型对象Format方法 ......

zhengzhixiang
50分钟前
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部