daily pastebin goal
11%
SHARE
TWEET

Untitled

a guest Apr 20th, 2018 56 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #pragma once
  2.  
  3. #include <exception>
  4. #include <variant>
  5.  
  6. #include <experimental/coroutine>
  7. #include <experimental/net>
  8.  
  9. namespace ams::async {
  10. using std::experimental::coroutine_handle;
  11.  
  12. template <typename Object, typename Function, typename Result>
  13. struct Awaiter {
  14.   Object& _object;
  15.   Function _func;
  16.   std::variant<std::monostate, Result, std::error_code> _result;
  17.  
  18.   Awaiter(Object& object, Function&& func)
  19.       : _object{object}, _func{std::forward<Function>(func)}, _result{} {}
  20.  
  21.   bool await_ready() { return false; }
  22.  
  23.   Result await_resume() {
  24.     if (_result.index() == 2) throw std::system_error(std::get<2>(_result));
  25.  
  26.     return std::get<1>(std::move(_result));
  27.   }
  28.  
  29.   void await_suspend(coroutine_handle<> coro) {
  30.     _func(_object, [this, coro](std::error_code const& ec, Result r) mutable {
  31.       if (!ec) {
  32.         _result.template emplace<1>(std::move(r));
  33.       } else {
  34.         _result.template emplace<2>(ec);
  35.       }
  36.       coro.resume();
  37.     });
  38.   }
  39. };
  40.  
  41. template <typename Object, typename Function>
  42. struct Awaiter<Object, Function, void> {
  43.   Object& _object;
  44.   Function _func;
  45.   std::variant<std::monostate, std::error_code> _result;
  46.  
  47.   Awaiter(Object& object, Function&& func)
  48.       : _object{object}, _func{std::forward<Function>(func)}, _result{} {}
  49.  
  50.   bool await_ready() { return false; }
  51.  
  52.   void await_resume() {
  53.     if (_result.index() == 1) throw std::system_error(std::get<1>(_result));
  54.   }
  55.  
  56.   void await_suspend(coroutine_handle<> coro) {
  57.     _func(_object, [this, coro](std::error_code const& ec) mutable {
  58.       if (ec) {
  59.         this->_result.template emplace<1>(ec);
  60.       }
  61.       coro.resume();
  62.     });
  63.   }
  64. };
  65.  
  66. template <typename Result, typename Object, typename Function>
  67. auto make_awaiter(Object& object, Function&& function) {
  68.   return Awaiter<Object, Function, Result>{object,
  69.                                            std::forward<Function>(function)};
  70. }
  71.  
  72. template <typename Acceptor>
  73. auto async_accept(Acceptor& a) {
  74.   return make_awaiter<typename Acceptor::protocol_type::socket>(
  75.       a, [](Acceptor& acceptor, auto&& callback) {
  76.         acceptor.async_accept(std::forward<decltype(callback)>(callback));
  77.       });
  78. }
  79.  
  80. template <typename Socket, typename Endpoint>
  81. auto async_connect(Socket& socket, Endpoint ep) {
  82.   return make_awaiter<void>(
  83.       socket, [ep = std::move(ep)](Socket & socket, auto&& callback) {
  84.         socket.async_connect(ep, std::forward<decltype(callback)>(callback));
  85.       });
  86. }
  87.  
  88. template <typename Socket, typename MutableBuffer>
  89. auto async_read(Socket& socket, MutableBuffer buffer) {
  90.   return make_awaiter<const unsigned long>(
  91.       socket, [buffer = std::move(buffer)](Socket & socket, auto&& callback) {
  92.         std::experimental::net::async_read(
  93.             socket, buffer, std::forward<decltype(callback)>(callback));
  94.       });
  95. }
  96.  
  97. template <typename Socket, typename ConstantBuffer>
  98. auto async_write(Socket& socket, ConstantBuffer buffer) {
  99.   return make_awaiter<const unsigned long>(
  100.       socket, [buffer = std::move(buffer)](Socket & socket, auto&& callback) {
  101.         std::experimental::net::async_write(
  102.             socket, buffer, std::forward<decltype(callback)>(callback));
  103.       });
  104. }
  105. }  // namespace ams::async
RAW Paste Data
Top