I'm trying to implement my own boost::asio
operation, executed asynchronously during io_context.run()
.
Also I need to implement a cancellable operation which waits for some condition / predicate is met (or boost::signals2::signal
is called) - and next, calls any completion handler in io_context
thread? Is such functionality already available in Boost?
My code is inspired by Boost documentation:
- https://www.boost.org/doc/libs/1_82_0/doc/html/boost_asio/reference/asynchronous_operations.html
- https://www.boost.org/doc/libs/1_82_0/doc/html/boost_asio/example/cpp14/operations/composed_3.cpp
#include <boost/asio.hpp>
#include <iostream>
/// From boost documentation:
/// — If the initiating function is not a member function,
/// the associated executor is that returned by the get_executor member function
/// of the first argument to the initiating function.
struct executor_owner
{
using executor_type = boost::asio::io_context;
executor_type* m_executor = nullptr;
explicit executor_owner(executor_type& ex)
: m_executor(&ex)
{
}
executor_type& get_executor() BOOST_ASIO_NOEXCEPT
{
std::cout << "get_executor() called." << std::endl;
return *m_executor;
}
};
/// My initiating function
template<class CompletionToken>
auto async_xyz(executor_owner executorOwner, CompletionToken&& token)
{
using completion_handler_t = typename boost::asio::async_completion<CompletionToken, void(executor_owner&)>::completion_handler_type;
return boost::asio::async_initiate<CompletionToken, void(executor_owner&)>(
[](completion_handler_t completion_handler, executor_owner& owner) {
// initiate the operation and cause completion_handler to be invoked
// with the result
std::cout << "I'm performing the async func operation here!" << std::endl;
completion_handler();
},
token, executorOwner);
}
int main()
{
boost::asio::io_context io_context;
executor_owner executorOwner(io_context);
async_xyz(executorOwner, []()
{
std::cout << "completion handler here!" << std::endl;
});
// I expect that completion handler will be called asynchronously, during io_context::run().
// Unfortunately, completion handler has already been called.
// std::cout << "io_context begin." << std::endl;
// io_context.run(); // It doesn't matter. completion handler
// std::cout << "io_context done." << std::endl;
return 0;
}
// Output:
// I'm performing the async func operation here!
// completion handler here!
My questions:
- How to implement custom async operation compliant with
boost::asio
design? - Why my executor wasn't obtained using
get_executor()
method as described in boost documentation? - Does
boost::asio::async_initiate
internally posts operation toio_context
, or have I callio_context::post(...)
manually in my custom operation implementation (to trigger the completion handler)? - How to implement easy wait operation which waits for a met predicate or a signal?
- How to add timeout / cancellation functionality to such operation?
I'm using boost 1.82 and C++14 (but C++11 solution is preferred).
All hints welcome, regards. And in case of down vote, please explain what's wrong.