我的带有 boost asio 和 std::async 的 snap 版本。没有使用睡眠。
#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/noncopyable.hpp>
#include <chrono>
#include <future>
#include <memory>
#include <iostream>
class MonotonicExecutor
: public boost::noncopyable,
public std::enable_shared_from_this<MonotonicExecutor> {
typedef std::function<void()> Functor;
public:
MonotonicExecutor(boost::posix_time::time_duration trig)
: m_service(),
m_serviceWork(
std::make_shared<boost::asio::io_service::work>(m_service)),
m_deadlineTimer(m_service), m_trigger(trig) {
auto fut = std::async(std::launch::async, [&]() { m_service.run(); });
fut.wait_for(std::chrono::milliseconds(1));
}
void executeAsync(Functor fun) {
m_deadlineTimer.expires_from_now(m_trigger);
m_deadlineTimer.async_wait(std::bind(&MonotonicExecutor::execute,
shared_from_this(),
std::placeholders::_1, fun));
}
void abort() { m_deadlineTimer.cancel(); }
private:
void execute(const boost::system::error_code &err, Functor fun) {
if (err != boost::asio::error::operation_aborted &&
m_deadlineTimer.expires_at() <=
boost::asio::deadline_timer::traits_type::now()) {
m_deadlineTimer.cancel();
fun();
m_deadlineTimer.expires_from_now(m_trigger);
m_deadlineTimer.async_wait(std::bind(&MonotonicExecutor::execute,
shared_from_this(),
std::placeholders::_1, fun));
}
}
private:
boost::asio::io_service m_service;
std::shared_ptr<boost::asio::io_service::work> m_serviceWork;
boost::asio::deadline_timer m_deadlineTimer;
boost::posix_time::time_duration m_trigger;
};
int main(int argc, char *argv[]) {
auto executor =
std::make_shared<MonotonicExecutor>(boost::posix_time::seconds(3));
executor->executeAsync([&]() {
std::cout << boost::posix_time::to_iso_string(
boost::posix_time::second_clock::local_time())
<< std::endl;
});
auto stop = std::chrono::system_clock::now() + std::chrono::seconds(30);
while (std::chrono::system_clock::now() < stop) {
std::this_thread::sleep_for(std::chrono::seconds(1));
}
executor->abort();
std::cout << "Wait and see if the task is aborted" << std::endl;
stop = std::chrono::system_clock::now() + std::chrono::seconds(30);
while (std::chrono::system_clock::now() < stop) {
std::this_thread::sleep_for(std::chrono::seconds(1));
}
return 0;
}