部分timer->cpp代码-程序员宅基地

133054_e2nJ_3244697.png

 

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

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

转载于:https://my.oschina.net/u/3244697/blog/1503874

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/chusi8795/article/details/100617676

智能推荐

mysql查看relaylog参数_MySQL relay log 详细参数解释-程序员宅基地

文章浏览阅读1.6k次。前言:MySQL进行主主复制或主从复制的时候会在home目录下面产生相应的relay log,本文档总结这些相关参数的定义及解释.1、什么是relay logThe relay log, like the binary log, consists of a set of numbered files containing events that describe database changes,..._mysql 查看relay log

SpringBoot之与dubbo集成(dubbo-spring-boot-starter 2.0.0)-yellowcong_dubbo-spring-boot-autoconfigure-程序员宅基地

文章浏览阅读1.5w次,点赞2次,收藏15次。官方文档https://github.com/apache/incubator-dubbo-spring-boot-project参考文章https://www.cnblogs.com/jaycekon/p/SpringBootDubbo.html_dubbo-spring-boot-autoconfigure

ibm服务器raid信息,ibm服务器+RAID配置全程(国外英文资料).doc-程序员宅基地

文章浏览阅读304次。ibm服务器RAID配置全程(国外英文资料)ibm服务器+RAID配置全程(国外英文资料)The IBM server RAID configuration is completeA, RAID is introducedThe abbreviation of RAID is Redundent Array of Inexpensive Disks, literal translation for..._ibm serveraid configuration

html 访问wcf,return html from wcf service-程序员宅基地

文章浏览阅读76次。I know this is an old post, but for a service that will only be hosted in IIS, here is an easy way to return html:[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMod..._wcf服务返回html

中呜机器人编程视频教程_中鸣快车编程入门篇—5.1补充的知识.doc-程序员宅基地

文章浏览阅读5.6k次。中鸣机器人快车编程人门篇视频——补充知识选对控制器型号(RCU类型)使用机器人快车软件时,需要选好对应的控制器类型,控制器类型选择如下图所示:(注意每更换一次RCU类型需要重新启动软件)。2、马达方向控制器可以更改马达的初始转动方向,如:假设M1以50的速度转动是顺时针转动,在控制器上的马达功能处修改方向后,运行同样的程序马达将逆时针转动。马达初始方向的修改方法如下:3、变量类型建立变量时注意修改..._中鸣机器人编程教程

MySQL中引入存储引擎意义是_【MySQL】MySQL之浅谈MySQL的存储引擎-程序员宅基地

文章浏览阅读136次。什么是MySql数据库通常意义上,数据库也就是数据的集合,具体到计算机上数据库可以是存储器上一些文件的集合或者一些内存数据的集合。我们通常说的MySql数据库,sql server数据库等等其实是数据库管理系统,它们可以存储数据,并提供查询和更新数据库中的数据的功能等等。根据数据库如何存储数据和如何操作数据的实现机制不同,这些数据库之间即有区别又有共同点。MySql数据库是开放源代码的关系型数据库..._mysql的存储引擎的意义

随便推点

android网易云信使用方法,Android集成网易云信IM的2个坑及解决方法-程序员宅基地

文章浏览阅读355次。0、APP直接调用 SDK 登陆方法,登录成功后,使用UIKit打开单聊页面出错。报错信息:报错信息显示:在UserInfoHelper类getUserTitleName方法中NimUIKit.getAccount()为空,即NimUIKitImpl.account为空(2)但使用UIKit提供的登录方法,进入聊天界面,没问题,这是怎么回事呢?点击到NimUIKit.login一直追寻下去,可以..._android 云信im 打开单聊界面,页面闪退

unity3d中教你如何获得物体的尺寸_unity标物体尺寸-程序员宅基地

文章浏览阅读2.6k次。1:获得诸如Plane、Cube的size。 1):可以为它们添加Collider,然后使用XXX.collider.bounds.size;该方法获得的size和缩放比例有关,是一一对应的,缩放比例一旦改变,size也改变。获得terrain的尺寸,在terrain的scale为1的情况下 terrainWidth = terrain.collider.bound_unity标物体尺寸

python在线投票系统系统_基于轮询实现实时的在线投票系统-程序员宅基地

文章浏览阅读2.3k次。需求用户在投票的页面可以实时的监测到,投票详情在这里我会通过轮询和长轮询(推荐使用这个,可以减少请求数,实时性也好)的方法来实现基于轮询实现投票系统大致的思路是前端开启一个定时器每隔10秒定时的向服务器获取投票的结果from flask import Flask,render_template,request,jsonifyapp = Flask(__name__)USERS = {'1':{'n..._python投票系统

Stack类详解-程序员宅基地

文章浏览阅读3.2k次,点赞2次,收藏19次。1.Activity,Window与View的关系流程解析: Activity调用startActivity后最后会调用attach方法,然后在PolicyManager实现一个Ipolicy接口,接着实现一个Policy对象,接着调用makenewwindow(Context)方法,该方法会返回一个PhoneWindow对象,而PhoneWindow 是Window的子类,在..._stack类

点云离群点剔除 — open3d python_open3d 过滤离群点-程序员宅基地

文章浏览阅读1.2w次,点赞8次,收藏43次。点云离群点剔除 — open3d python,三种点云离群点剔除方法,含数据与源码。_open3d 过滤离群点

php cache()类,PHP的cache类 - 我的PHP之旅|php,php空间,php主机,国外php空间,php空间申请...-程序员宅基地

文章浏览阅读348次。class cache{var $cache_dir = 'cache/';//This is the directory where the cache files will be stored;var $cache_time = 1000;//How much time will keep the cache files in seconds.var $caching = false;var ..._php cache类

推荐文章

热门文章

相关标签