c++11 写一个定时器模型

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";
}


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值