背景
有时候调用一个耗时较长的函数,容易造成程序卡死,这个时候我们希望能增加一个超时参数,即函数在超时之前执行完成我们认为执行成功,反之认为执行超时
经过调研,实现方法大概分为3种:
1.利用boost中的thread::timed_join实现,但是需要依赖boost库
2.利用future特性实现,但是future析构时,会等线程结束,会需要额外耗费一个线程去负责future的析构
3.利用thread+条件变量实现
如下代码为thread+条件变量
#include <iostream>
#include <mutex>
#include <thread>
#include <condition_variable>
#include <functional>
struct ProcessParm
{
std::condition_variable cv;
std::mutex mtx;
int result = 0xffffffff;
};
class SyncTimeoutProxyThread
{
public:
SyncTimeoutProxyThread()
{
_curRunningNum.store(0);
}
int syncCallWithTimeOut(std::function<int()>&& func, uint32_t timeout)
{
if (timeout > 0)
{
_curRunningNum.store(_curRunningNum.load() + 1);
if (_curRunningNum.load() > _upperLimitRunningTask) {
uint32_t curRunningNum = _curRunningNum.load();
printf("current running num over upper limit ,current running task %d", curRunningNum);
}
std::shared_ptr<ProcessParm> processParm = std::make_shared<ProcessParm>();
std::thread t([](std::function<int()>&& func, std::shared_ptr<ProcessParm> parm) {
parm->result = func();
parm->cv.notify_one();
_curRunningNum.store(_curRunningNum.load() - 1);
}, std::move(func), processParm);
t.detach();
std::unique_lock<std::mutex> lockcv(processParm->mtx);
std::cv_status cvsts = processParm->cv.wait_for(lockcv, std::chrono::milliseconds(timeout));
if (cvsts == std::cv_status::timeout)
{
return 0xffffffff;
}
else
{
return processParm->result;
}
}
return func();
}
~SyncTimeoutProxyThread()
{
}
private:
uint32_t _upperLimitRunningTask = 100;
static std::atomic_uint32_t _curRunningNum;
};
std::atomic_uint32_t SyncTimeoutProxyThread::_curRunningNum;
int main()
{
SyncTimeoutProxyThread funcProc;
int rlt = funcProc.syncCallWithTimeOut([]() {
std::this_thread::sleep_for(std::chrono::milliseconds(6));
return 1;
}, 5);
if (0xffffffff == rlt)
{
printf("process TimeOut\n");
}
else
{
printf("process ok ,rlt = %d\n",rlt);
}
return 0;
}