自定义定时器

自定义定时器

#include <iostream>
#include <sys/epoll.h>
#include <chrono>
#include <functional>
#include <memory>
#include <set>
int64_t gid{0};

struct NodeBase
{
    time_t expire;//过期时间
    int64_t id;//全局唯一id
};

struct TimerNode : public NodeBase
{
    using Callback = std::function<void(const TimerNode &node)>;
    Callback cb;

    TimerNode(time_t exp, int64_t id, Callback cb)
    {
        this->expire = exp;
        this->id = id;
        this->cb = cb;
    }
};

bool operator < (const NodeBase& lhd, const NodeBase& rhd)
{
    if(lhd.expire < rhd.expire)
        return true;
    else if(lhd.expire > rhd.expire)
        return false;

    return lhd.id < rhd.id;
}
class CTimer
{
public:
    //系统启动到现在的时间
    static time_t GetTick()
    {
        auto sc = std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now());
        auto tmp = std::chrono::duration_cast<std::chrono::milliseconds>(sc.time_since_epoch());
        return tmp.count();
    }

    NodeBase AddTimer(time_t msec, TimerNode::Callback cb)
    {
        time_t expire = GetTick()+msec;
        auto ele = timer.emplace(expire, GenID(), cb);
        return static_cast<NodeBase>(*ele.first);
    }

    bool DelTimer(NodeBase &node)
    {
        //C++14才能find到
        auto iter = timer.find(node);
        if(iter != timer.end())
        {
            timer.erase(iter);
            return true;
        }

        return false;
    }

    bool CheckTimer()
    {
        auto iter = timer.begin();
        if(iter != timer.end() && iter->expire <= GetTick())
        {
            iter->cb(*iter);
            timer.erase(iter);
            return true;
        }
        return false;
    }

    time_t TimeToSleep()
    {
        auto iter = timer.begin();
        if(iter == timer.end()) return -1;
        time_t diss = iter->expire - GetTick();
        return diss > 0 ? diss : 0;
    }

private:
    static int64_t GenID()
    {
        return gid++;
    }
private:
    std::set<TimerNode, std::less<>> timer;
};



int main()
{
    int epfd = epoll_create(1);
    epoll_event ev[64] = {0};
    std::unique_ptr<CTimer> timer(new CTimer());
    int i=1000;
    timer->AddTimer(1000, [&](const TimerNode &node){
        std::cout << CTimer::GetTick() << " node id:" << node.id
            << " i=" << i++ << std::endl;
    });
    timer->AddTimer(1000, [&](const TimerNode &node){
        std::cout << CTimer::GetTick() << " node id:" << node.id
            << " i=" << i++ << std::endl;
    });   
    timer->AddTimer(3000, [&](const TimerNode &node){
        std::cout << CTimer::GetTick() << " node id:" << node.id
            << " i=" << i++ << std::endl;
    });  

    auto node = timer->AddTimer(2100, [&](const TimerNode &node){
        std::cout << CTimer::GetTick() << " node id:" << node.id
            << " i=" << i++ << std::endl;
    }); 
    timer->DelTimer(node);

    while(true)
    {
        // timeout 要阻塞等待多长时间
        // -1 永久阻塞
        // 0 如果网络事件触发,立刻返回
        // >0 比如1000阻塞等待1s
        int n = epoll_wait(epfd, ev, 64, timer->TimeToSleep());
        for(int i=0; i<n; i++)
        {
            //处理网络事件
        }
        //处理定时事件
        while(timer->CheckTimer());
    }
    return 0;
}
luni@DESKTOP-Q66QS5Q:~$ g++ timer.cc -o timer -std=c++14
luni@DESKTOP-Q66QS5Q:~$ ./timer
78831834 node id:0 i=1000
78831835 node id:1 i=1001
78832934 node id:3 i=1002
78833834 node id:2 i=1003
posted @ 2022-11-15 10:07  不知云深处  阅读(48)  评论(0编辑  收藏  举报