Guest User

Untitled

a guest
Apr 20th, 2018
82
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.13 KB | None | 0 0
  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
Add Comment
Please, Sign In to add comment