1:单个线程可以添加多个定时器
2:完全依赖c++11
3:添加删除定时器是同步的
头文件
WorkerThread.h
#ifndef WorkerThread_H_
#define WorkerThread_H_
#include <functional>
#include <stdint.h>
#include <stdio.h>
#include <list>
#include <iostream>
#include <thread>
#include <mutex>
#include <chrono>
#include <condition_variable>
#include <map>
#include <future>
#include <stdint.h>
#include <string>
class Event
{
public:
int64_t Wait()
{
std::unique_lock<decltype(m_MutexCondition)> lock{ m_MutexCondition };
m_Condition.wait(lock, [&]()->bool { return ret != -1; }); // suspend and wait ...
return ret;
}
void Set(int64_t re)
{
std::unique_lock<decltype(m_MutexCondition)> lock(m_MutexCondition);
ret = re;
m_Condition.notify_one();
}
std::mutex m_MutexCondition;
std::condition_variable m_Condition;
int64_t ret = -1;
};
class Timer
{
public:
Timer(int64_t delay, std::function<bool()> cb) : m_iDelay(delay), m_cb(cb) {};
~Timer() {};
int64_t m_iDelay = 0;
std::function<bool()> m_cb;
int64_t m_iTimerId = -1;
};
using Task = std::function<void()>; //定义类型
class WorkerThread
{
public:
WorkerThread();
int32_t StartRun();
void StopRun();
~WorkerThread();
public:
// 添加一个定时器
int64_t AddTimer(int64_t iDelayUs, std::function<bool()> fcb);
// 删除一个定时器
int32_t DelTimer(int64_t timerId);
// 异步任务
void PostTask(Task task);
// 同步执行任务
void InvokTask(Task task);
private:
void RunLoop();
int64_t getCurrentTicket();
int32_t addTimerInner(std::shared_ptr<Timer>& _Timer);
int32_t delTimerInner(int64_t timerId);
int64_t flushDelayTask(uint64_t now_time);
int64_t getMinDelay();
private:
std::multimap<uint64_t, std::shared_ptr<Timer> > m_delayTask;
std::mutex _mutex;
std::condition_variable _condition;
bool m_bStart = false;
int64_t m_iTimerId = 0;
std::list<Task> _queue;
std::thread* m_loopThread = NULL;
bool m_bExitThread = false;
std::thread::id _loopThreadId;
};
class EventLoop
{
public:
EventLoop(const EventLoop&) = delete;
EventLoop& operator = (const EventLoop&) = delete;
EventLoop(uint32_t num_threads = 1); //std::thread::hardware_concurrency()
virtual ~EventLoop();
std::shared_ptr<WorkerThread> GetTaskScheduler();
// 添加一个定时器
int64_t AddTimer(int64_t iDelayUs, std::function<bool()> fcb);
// 删除一个定时器
int32_t DelTimer(int64_t timerId);
// 异步任务
void PostTask(Task task);
// 同步执行任务
void InvokTask(Task task);
void Loop();
void Quit();
private:
std::mutex mutex_;
uint32_t num_threads_ = 1;
uint32_t index_ = 1;
std::vector<std::shared_ptr<WorkerThread>> task_schedulers_;
};
#endif
WorkerThread.cpp 文件
#include "WorkerThread.h"
WorkerThread::WorkerThread()
{
}
WorkerThread::~WorkerThread()
{
StopRun();
}
int64_t WorkerThread::getCurrentTicket()
{
//std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
//std::chrono::steady_clock::time_point t11;
//int64_t duration = std::chrono::duration_cast<std::chrono::microseconds>(t1 - t11).count();
//int64_t duration = std::chrono::duration_cast<std::chrono::milliseconds>(t1 - t11).count();
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
}
int32_t WorkerThread::StartRun()
{
m_loopThread = new std::thread(&WorkerThread::RunLoop, this);
std::unique_lock<std::mutex> lock(_mutex);
_condition.wait(lock, [this]() { return m_bStart == true; });
if (m_loopThread)
{
return 0;
}
return -1;
}
void WorkerThread::StopRun()
{
m_bExitThread = true;
{
std::unique_lock<std::mutex> lock(_mutex);
_queue.push_back([]() {int a; });
}
_condition.notify_one();
if (m_loopThread)
{
m_loopThread->join();
delete m_loopThread;
m_loopThread = 0;
}
}
int64_t WorkerThread::AddTimer(int64_t iDelay, std::function<bool()> fcb)
{
//using RetType = decltype(int32_t(Timer&&)); // typename std::result_of<F(Args...)>::type, 函数 f 的返回值类型
#if 0
auto t_timer = std::make_shared<Timer>(iDelay, fcb);
auto task = std::make_shared<std::packaged_task<int64_t(std::shared_ptr<Timer>)>>(
bind(&WorkerThread::addTimerInner, this, (t_timer)));
std::future<int64_t> future = task->get_future();
{
std::lock_guard<std::mutex> lock(_mutex);
_queue.push_back([task]() {
std::shared_ptr<Timer> a;
(*task)(a);
});
}
_condition.notify_one();
int32_t ret = future.get();
return ret;
#else
Event tEvent;
auto t_timer = std::make_shared<Timer>(iDelay, fcb);
{
std::unique_lock<std::mutex> lock(_mutex);
_queue.push_back([this, &t_timer, &tEvent]() {
m_iTimerId++;
t_timer->m_iTimerId = m_iTimerId;
uint64_t time_line = getCurrentTicket() + t_timer->m_iDelay;
m_delayTask.emplace(time_line, std::move(t_timer));
tEvent.Set(m_iTimerId);
});
}
_condition.notify_one();
return tEvent.Wait();
#endif
}
void WorkerThread::PostTask(Task task)
{
{
std::unique_lock<std::mutex> lock(_mutex);
Event tEvent;
_queue.push_back([task]() {
task();
});
}
_condition.notify_one();
}
void WorkerThread::InvokTask(Task task)
{
Event tEvent;
{
std::unique_lock<std::mutex> lock(_mutex);
_queue.push_back([task, &tEvent]() {
task();
tEvent.Set(0);
});
}
_condition.notify_one();
printf("Wait before \n");
tEvent.Wait();
}
int32_t WorkerThread::DelTimer(int64_t timerId)
{
#if 0
auto task = std::make_shared<std::packaged_task<int32_t(int32_t)>>(
std::bind(&WorkerThread::delTimerInner, this, (timerId)));
std::future<int32_t> future = task->get_future();
{
std::lock_guard<std::mutex> lock(_mutex);
_queue.push_back([task]() {
(*task)(0);
});
}
_condition.notify_one();
int32_t ret = future.get();
return ret;
#else
Event tEvent;
{
std::unique_lock<std::mutex> lock(_mutex);
_queue.push_back([&tEvent, timerId, this]() {
std::multimap<uint64_t, std::shared_ptr<Timer> >::iterator it = m_delayTask.begin();
for (; it != m_delayTask.end();)
{
std::shared_ptr<Timer> pTimer = it->second;
if (pTimer->m_iTimerId == timerId)
{
it = m_delayTask.erase(it);
tEvent.Set(0);
return;
}
else
{
it++;
}
}
tEvent.Set(1);
return;
});
}
_condition.notify_one();
return tEvent.Wait();
#endif
}
void WorkerThread::RunLoop()
{
_loopThreadId = std::this_thread::get_id();
m_bStart = true;
_condition.notify_one();
while (!m_bExitThread)
{
int64_t delay = getMinDelay(); // 处理定时器任务
std::list<Task> t_queue;
{
std::unique_lock<std::mutex> lock(_mutex);
//_condition.wait_for(lock, std::chrono::milliseconds(delay), [this]() { return !_queue.empty(); });
_condition.wait_for(lock, std::chrono::microseconds(delay), [this]() { return !_queue.empty(); });
if (!_queue.empty())
{
t_queue.swap(_queue);
}
}
// 处理任务
if (!t_queue.empty())
{
for (std::list<Task>::iterator it = t_queue.begin(); it != t_queue.end(); it++)
{
Task task = *it;
task();
}
t_queue.clear();
}
}
}
int32_t WorkerThread::addTimerInner(std::shared_ptr<Timer>& _Timer)
{
printf("delay:%lld \n", _Timer->m_iDelay);
m_iTimerId++;
_Timer->m_iTimerId = m_iTimerId;
uint64_t time_line = getCurrentTicket() + _Timer->m_iDelay;
m_delayTask.emplace(time_line, std::move(_Timer));
return m_iTimerId;
}
int32_t WorkerThread::delTimerInner(int64_t timerId)
{
std::multimap<uint64_t, std::shared_ptr<Timer> >::iterator it = m_delayTask.begin();
for (; it != m_delayTask.end();)
{
std::shared_ptr<Timer> pTimer = it->second;
if (pTimer->m_iTimerId == timerId)
{
it = m_delayTask.erase(it);
return 0;
}
else
{
it++;
}
}
return -1;
}
int64_t WorkerThread::getMinDelay() {
auto it = m_delayTask.begin();
if (it == m_delayTask.end()) {
//没有剩余的定时器了
return 0;
}
auto now = getCurrentTicket();
if (it->first > now) {
//所有任务尚未到期
return it->first - now;
}
//执行已到期的任务并刷新休眠延时
return flushDelayTask(now);
}
int64_t WorkerThread::flushDelayTask(uint64_t now_time) {
//printf("############# sleep :%llu \n", now_time);
decltype(m_delayTask) taskCopy;
taskCopy.swap(m_delayTask);
uint64_t start = getCurrentTicket();
for (auto it = taskCopy.begin(); it != taskCopy.end() && it->first <= now_time; it = taskCopy.erase(it)) {
//已到期的任务
try {
//auto next_delay = (*(it->second))();
std::shared_ptr<Timer> pTimer = it->second;
if (pTimer->m_cb)
{
bool ret = pTimer->m_cb();
if (ret)
{
m_delayTask.emplace(pTimer->m_iDelay + now_time, std::move(it->second));
}
}
}
catch (std::exception& ex) {
//ErrorL << "EventPoller执行延时任务捕获到异常:" << ex.what();
}
}
uint64_t end = getCurrentTicket();
int64_t useTime = end - start;
if (useTime > 11)
{
//printf("timers_poll::flushDelayTask useTimer = %d \n", useTime);
}
taskCopy.insert(m_delayTask.begin(), m_delayTask.end());
taskCopy.swap(m_delayTask);
auto it = m_delayTask.begin();
if (it == m_delayTask.end()) {
//没有剩余的定时器了
return 0;
}
//最近一个定时器的执行延时
int64_t t_sleep = it->first - getCurrentTicket();
if (t_sleep < -1)
{
printf("timers_poll::flushDelayTask t_sleep = %lld \n", t_sleep);
}
return t_sleep > 0 ? t_sleep : 0;
}
EventLoop::EventLoop(uint32_t num_threads)
: index_(1)
{
num_threads_ = 1;
if (num_threads > 0) {
num_threads_ = num_threads;
}
this->Loop();
}
EventLoop::~EventLoop()
{
this->Quit();
}
std::shared_ptr<WorkerThread> EventLoop::GetTaskScheduler()
{
std::lock_guard<std::mutex> locker(mutex_);
if (task_schedulers_.size() == 1) {
return task_schedulers_.at(0);
}
else {
auto task_scheduler = task_schedulers_.at(index_);
index_++;
if (index_ >= task_schedulers_.size()) {
index_ = 1;
}
return task_scheduler;
}
return nullptr;
}
int64_t EventLoop::AddTimer(int64_t iDelayUs, std::function<bool()> fcb)
{
std::lock_guard<std::mutex> locker(mutex_);
if (task_schedulers_.size() > 0) {
return task_schedulers_[0]->AddTimer(iDelayUs, fcb);
}
return -1;
}
int32_t EventLoop::DelTimer(int64_t timerId)
{
std::lock_guard<std::mutex> locker(mutex_);
if (task_schedulers_.size() > 0) {
return task_schedulers_[0]->DelTimer(timerId);
}
return -1;
}
void EventLoop::PostTask(Task task)
{
std::lock_guard<std::mutex> locker(mutex_);
if (task_schedulers_.size() > 0) {
task_schedulers_[0]->PostTask(task);
}
}
void EventLoop::InvokTask(Task task)
{
std::lock_guard<std::mutex> locker(mutex_);
if (task_schedulers_.size() > 0) {
return task_schedulers_[0]->InvokTask(task);
}
return;
}
void EventLoop::Loop()
{
std::lock_guard<std::mutex> locker(mutex_);
if (!task_schedulers_.empty()) {
return;
}
for (uint32_t n = 0; n < num_threads_; n++)
{
std::shared_ptr<WorkerThread> task_scheduler_ptr(new WorkerThread());
task_scheduler_ptr->StartRun();
task_schedulers_.push_back(task_scheduler_ptr);
}
}
void EventLoop::Quit()
{
std::lock_guard<std::mutex> locker(mutex_);
for (auto iter : task_schedulers_) {
iter->StopRun();
}
task_schedulers_.clear();
}
main.cpp
// condition_variable.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <thread>
#include <mutex>
#include <string>
#include "WorkerThread.h"
int main()
{
WorkerThread tWorkerThread;
tWorkerThread.StartRun();
Event tEvern;
tWorkerThread.PostTask([&tEvern]() {
printf("$$$$$$$$$$$$ \n");
tEvern.Set();
});
tEvern.Wait();
printf("over \n");
tWorkerThread.InvokTask([]() {
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
});
printf("over 1 \n");
getchar();
std::cout << "Hello World!\n";
}