#include "async_callback.h"
#include
#include
using namespace std;
int main() {
int a = 0, b = 0, c = 0;
AsyncTask* task1 = new AsyncTask([&a](){
sleep(2);
for (int i = 0; i < 10000; ++i) {
++a;
}
});
AsyncTask* task2 = new AsyncTask([&b](){
sleep(2);
for (int i = 0; i < 10000; ++i) {
++b;
}
});
if (!task1->get(1)) {
cout << "task1超时" << endl;
}
if (task2->get()) {
cout << "task2没超时" << endl;
}
task1->restart();
task2->restart();
task1->get();
task2->get();
cout << a << endl;
cout << b << endl;
cout << "task1执行时间:" << task1->executionTime() << endl;
cout << "task2执行时间:" << task2->executionTime() << endl;
return 0;
}
打印结果:
task1超时
task2没超时
20000
20000
task1执行时间:2.00009
task2执行时间:2.00009
// Simple asynchronous tasks with timeout
// Author: Y. F. Zhang
// Date: 2023-09-21
#ifndef ASYNC_CALLBACK_H
#define ASYNC_CALLBACK_H
#include
#include
#include
#include
#include
#include
#include
#include
#include
class Timer {
public:
Timer() {
offsetTime_ = 0;
timerState_ = TIMERSTOP;
}
void timerStart() {
timerState_ = TIMERRUN;
timeStamp_ = getWallTime();
}
double elapsedTime() {
if (timerState_ == TIMERPAUSE) {
return offsetTime_;
}
curTime_ = getWallTime() - timeStamp_ + offsetTime_;
if (timerState_ == TIMERSTOP) return 0;
return curTime_;
}
void pauseTimer() {
offsetTime_ += getWallTime() - timeStamp_;
timerState_ = TIMERPAUSE;
}
void stopTimer() {
offsetTime_ = 0;
curTime_ = 0;
timerState_ = TIMERSTOP;
}
private:
double getWallTime() {
struct timeval time ;
if (gettimeofday(&time,NULL)){
return 0;
}
return (double)time.tv_sec + (double)time.tv_usec * .000001;
}
double timeStamp_;
double curTime_;
double offsetTime_;
enum{
TIMERSTOP,
TIMERRUN,
TIMERPAUSE
} timerState_;
};
namespace AsyncTaskException {
class GetButTaskStopErr: public std::exception {
const char* what() const throw () {
return "invoke get method but task is stop!";
}
};
class GetExecutionTimeButTaskStopErr: public std::exception {
const char* what() const throw () {
return "invoke executionTime method but task is stop!";
}
};
}
using func = std::function<void()>;
class AsyncTask {
private:
enum {
TASKRUNNING,
TASKSTOP,
TASKFINISHED
} taskState_;
func callback_;
std::mutex mtx_;
std::condition_variable cond_;
std::atomic_bool completedFlag_;
std::thread* taskThread_;
Timer timer_;
void initTask() {
timer_.stopTimer();
taskState_ = TASKSTOP;
completedFlag_.store(false);
if (taskThread_ != nullptr) {
delete taskThread_;
taskThread_ = nullptr;
}
}
void runTask() {
auto wrapperCallback = [this]() {
try {
timer_.timerStart();
callback_();
timer_.pauseTimer();
completedFlag_.store(true);
} catch (std::exception e) {
fprintf(stderr, "%s", e.what());
}
taskState_ = TASKFINISHED;
cond_.notify_one();
};
taskState_ = TASKRUNNING;
taskThread_ = new std::thread(wrapperCallback);
taskThread_->detach();
}
public:
AsyncTask(func&& callback) {
this->callback_ = callback;
restart();
}
void restart() {
initTask();
runTask();
}
double executionTime() {
if (taskState_ == TASKSTOP) {
throw AsyncTaskException::GetExecutionTimeButTaskStopErr();
}
return timer_.elapsedTime();
}
~AsyncTask() {
if (taskThread_ != nullptr) {
delete taskThread_;
}
}
bool get(size_t timeoutSec = 0) {
if (taskState_ == TASKSTOP) {
throw AsyncTaskException::GetButTaskStopErr();
}
std::unique_lock<std::mutex> lk(mtx_);
if (timeoutSec == 0) {
cond_.wait(lk, [this](){return completedFlag_.load();});
} else {
return cond_.wait_for(lk, std::chrono::seconds(timeoutSec), [this](){return completedFlag_.load();});
}
return true;
}
};
#endif