自定义定时器
#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