Skip to content

Instantly share code, notes, and snippets.

@inetic
Last active September 7, 2024 09:44
Show Gist options
  • Save inetic/dc9081baf45ec4b60037 to your computer and use it in GitHub Desktop.
Save inetic/dc9081baf45ec4b60037 to your computer and use it in GitHub Desktop.
Example usage of boost::asio::async_result
// Example of how to use boost::asio::async_result
#include <iostream>
#include <boost/asio.hpp>
#if BOOST_VERSION >= 106600
template<typename CompletionToken>
typename boost::asio::async_result
<CompletionToken, void(boost::system::error_code, std::string)>::return_type
my_fancy_async_operation( boost::asio::io_service& ios
, const std::string& message
, CompletionToken&& token)
{
namespace asio = boost::asio;
namespace system = boost::system;
using Sig = void(system::error_code, std::string);
using Result = asio::async_result<CompletionToken, Sig>;
using Handler = typename Result::completion_handler_type;
Handler handler(std::forward<decltype(token)>(token));
Result result(handler);
ios.post([handler, message]() mutable {
handler(system::error_code(), message);
});
return result.get();
}
#else
// Note: the handler signatures here must contain
// boost::system::error_code as first argument (not std::error_code)
// for asio to understand it is to indicate errors.
template<typename CompletionToken>
typename boost::asio::async_result
< typename boost::asio::handler_type< CompletionToken
, void(boost::system::error_code, std::string)
>::type
>::type
my_fancy_async_operation( boost::asio::io_service& ios
, const std::string& message
, CompletionToken&& token)
{
namespace asio = boost::asio;
namespace system = boost::system;
using handler_type = typename asio::handler_type
<CompletionToken, void(system::error_code, std::string)>::type;
handler_type handler(std::forward<decltype(token)>(token));
// The result must be defined here, otherwise we'll get segmentation
// fault when using coroutines (don't understand why though).
asio::async_result<handler_type> result(handler);
ios.post([handler, message]() mutable {
handler(system::error_code(), message);
});
return result.get();
}
#endif
// Link flags: -lboost_coroutine // If using coroutines
// -lboost_context // If using coroutines
// -lboost_system // For asio
// -lpthread // If using futures
#define USE_CALLBACKS 1
#define USE_FUTURES 1
#define USE_COROUTINES 1
#if USE_FUTURES
# include <thread>
# include <boost/asio/use_future.hpp>
#endif
#if USE_COROUTINES
# include <boost/asio/spawn.hpp>
#endif
int main() {
using namespace std;
using namespace boost;
asio::io_service ios;
#if USE_CALLBACKS
{
my_fancy_async_operation( ios
, "handler"
, []( system::error_code, const string& msg) {
cout << "hello " << msg << endl;
});
ios.run();
}
#endif
#if USE_FUTURES
ios.reset();
{
asio::io_service::work work(ios);
thread io_thread([&ios]() { ios.run(); });
try {
auto msg = my_fancy_async_operation(ios
, "future"
, boost::asio::use_future).get();
cout << "hello " << msg << endl;
}
catch (boost::system::system_error error) {
// ...
}
ios.stop();
io_thread.join();
}
#endif
#if USE_COROUTINES
ios.reset();
{
boost::asio::spawn(ios, [&ios](boost::asio::yield_context yield) {
system::error_code error;
auto msg = my_fancy_async_operation(ios, "coroutine", yield[error]);
cout << "hello " << msg << endl;
});
ios.run();
}
#endif
}
@Necktwi
Copy link

Necktwi commented Jan 26, 2017

what have you done bro! Can you please write a simpler use case? I just want to find out acceptor_.async_accept is actually listening on the port or not.

@jrversteegh
Copy link

Excellent! Exactly what I was looking for.

@koraxkorakos
Copy link

Great! Have long been searching for a good example. Looking at Asio code directly is just too confusing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment