1. 比较少代码的方案,测试正常 【std::async + std:condition_varibale + std::function】
但是有点不理解,多个线程同时调asyncWait,如果把asyncWait返回的std::future<void>全部赋值给同一个对象,是否会有线程安全问题 但是测试是正常的
#include <iostream>
#include <chrono>
#include <future>
#include <thread>
#include <mutex>
#include <condition_variable>
class GpDeadTimer
{
public:
GpDeadTimer(){}
~GpDeadTimer(){}
//异步超时回调, 一定要接返回值,不然不会异步
std::future<void> asyncWait(int mesc, std::function<void()> callback_fun)
{
return std::async(std::launch::async, [this, mesc, callback_fun](){
std::unique_lock<std::mutex> lck(timer_mtx_);
stop_timer_ = false;
if (!timer_cv_.wait_for(lck, std::chrono::milliseconds(mesc), [this]{ return stop_timer_ == true; }))
{
callback_fun();
}
else
{
std::cout << "operator break\n";
}
});
}
void cancel()
{
{
std::lock_guard<std::mutex> lck(timer_mtx_);
stop_timer_ = true;
}
timer_cv_.notify_all();
}
private:
std::mutex timer_mtx_;
std::condition_variable timer_cv_;
std::atomic<bool> stop_timer_{true};
};
测试:

2. 比较复杂可能很多地方写的多余了
#ifndef TIMER_H
#define TIMER_H
#include <iostream>
#include <chrono>
#include <atomic>
#include <thread>
#include <mutex>
//实现同步或异步定时器
enum class eDeadType
{
eNoTimeout, /*timeout <= 0*/
eTimeout, /*正常超时退出*/
eOperator_break, /*主动终止*/
};
typedef void (*CallBackFunc)(eDeadType &type, void* arg);
class DeadLineTimerImpl
{
public:
DeadLineTimerImpl(){}
~DeadLineTimerImpl()
{
stop_timer.store(true);
if (wait_thread_.joinable())
{
wait_thread_.join();
}
}
DeadLineTimerImpl(const DeadLineTimerImpl&) = delete;
DeadLineTimerImpl& operator=(const DeadLineTimerImpl&) = delete;
//设置超时从当前时间起
void expires_from_now(int mesc)
{
wait_timeout_.store(mesc);
}
//取消超时操作
void setCancel()
{
stop_timer.store(true);
}
//同步等待
void wait()
{
if (wait_timeout_.load() <= 0)
return;
stop_timer = false;
auto deadtime = std::chrono::steady_clock::now() + std::chrono::milliseconds(wait_timeout_.load());
while(std::chrono::steady_clock::now() < deadtime && stop_timer.load() == false)
{//wait
}
return;
}
//异步等待
void async_wait(CallBackFunc timeout_func, void* arg)
{
mtx_.lock();
func_callback_ = timeout_func;
callback_host_ = arg;
if (wait_timeout_.load() <= 0){
eDeadType type = eDeadType::eNoTimeout;
if (this->func_callback_ != nullptr)
func_callback_(type, callback_host_);
return;
}
mtx_.unlock();
stop_timer.store( false);
auto func = [this](){
std::lock_guard<std::mutex> lock(mtx_);
auto deadtime = std::chrono::steady_clock::now() + std::chrono::milliseconds(wait_timeout_.load());
while(std::chrono::steady_clock::now() < deadtime && stop_timer.load() == false)
{ //wait
}
if (stop_timer.load() == false)
{
eDeadType type = eDeadType::eTimeout;
if (this->func_callback_ != nullptr){
func_callback_(type, callback_host_);
}
return;
}
eDeadType type = eDeadType::eOperator_break;
if (this->func_callback_ != nullptr){
func_callback_(type, callback_host_);
}
};
wait_thread_ = std::thread(func);
return;
}
private:
std::mutex mtx_;
CallBackFunc func_callback_;
void *callback_host_{nullptr};
std::atomic<bool> stop_timer{true};
std::atomic<int> wait_timeout_{3000};
std::thread wait_thread_;
};
#endif // TIMER_H
测试
#include "timer.h"
void timeout_handler(eDeadType &type, void *arg);
class test
{
public:
test(){}
void doOperator()
{
std::cout << "_____________start\n";
timer.expires_from_now(3000);
timer.async_wait(timeout_handler, this);
std::cout << "____________________end\n";
//主动打断
#if 1
std::this_thread::sleep_for(std::chrono::seconds(1));
timer.setCancel();
#endif
}
void timeout(eDeadType &type)
{
std::cout << "inter receive " << static_cast<int>(type) << std::endl;
switch (type) {
case eDeadType::eTimeout:
std::cout << "timeout success " << idx+3 << std::endl;
break;
case eDeadType::eNoTimeout:
std::cout << "no timeout " << idx << std::endl;
break;
case eDeadType::eOperator_break:
std::cout << "operator break success " << idx+4 << std::endl;
break;
}
}
private:
int idx = 20;
DeadLineTimerImpl timer;
};
void timeout_handler(eDeadType &type, void *arg)
{
std::cout << "call back: type: " << static_cast<int>(type) << std::endl;
reinterpret_cast<test*>(arg)->timeout(type);
}
int main(int argc, char *argv[])
{
test aa;
aa.doOperator();
return 0;
}

网友评论