No intro for this one, it’s too late.
Here’s the code:
extern boost::asio::io_service s_io_service; namespace silk { template<typename F> auto async(F f) -> boost::unique_future<decltype(f())> { typedef decltype(f()) result_type; typedef boost::packaged_task<result_type> packaged_task; auto task = std::make_shared<packaged_task>(std::move(f)); boost::unique_future<result_type> future = task->get_future(); s_io_service.post(boost::bind(&packaged_task::operator(), task)); return future; } }
It’s std::async replacement that uses a boost::asio::io_service as a dispatcher.
I use it for any operation that might take too long and it’s in the middle of my control loop – like saving new PIDs to disk ot the battery state.
Usage is pretty simple – pass a lambda and that lambda will be executed some time later from the thread that is doing the io_service::run()
silk::async([=]() { save_settings(); });
or
silk::async([=]() { autojsoncxx::to_pretty_json_file("battery_state.cfg", m_saved_state); QLOGI("Capacity used: {}mAh", m_capacity_used_mah); });
The function returns a boost::future so the result of the lambda can be pooled for.
I like the async ways. The future/promise mechanism is a very elegant way to express computations. It reminds me a bit of the Haskell’s lazyness.