concepts.hpp 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. // Copyright (c) 2022 Klemens D. Morgenstern
  2. //
  3. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. #ifndef BOOST_COBALT_CONCEPTS_HPP
  6. #define BOOST_COBALT_CONCEPTS_HPP
  7. #include <coroutine>
  8. #include <concepts>
  9. #include <utility>
  10. #include <boost/asio/error.hpp>
  11. #include <boost/asio/is_executor.hpp>
  12. #include <boost/asio/execution/executor.hpp>
  13. #include <boost/system/system_error.hpp>
  14. #include <boost/throw_exception.hpp>
  15. namespace boost::cobalt
  16. {
  17. // tag::outline[]
  18. template<typename Awaitable, typename Promise = void>
  19. concept awaitable_type = requires (Awaitable aw, std::coroutine_handle<Promise> h)
  20. {
  21. {aw.await_ready()} -> std::convertible_to<bool>;
  22. {aw.await_suspend(h)};
  23. {aw.await_resume()};
  24. };
  25. template<typename Awaitable, typename Promise = void>
  26. concept awaitable =
  27. awaitable_type<Awaitable, Promise>
  28. || requires (Awaitable && aw) { {std::forward<Awaitable>(aw).operator co_await()} -> awaitable_type<Promise>;}
  29. || requires (Awaitable && aw) { {operator co_await(std::forward<Awaitable>(aw))} -> awaitable_type<Promise>;};
  30. //end::outline[]
  31. struct promise_throw_if_cancelled_base;
  32. template<typename Promise = void>
  33. struct enable_awaitables
  34. {
  35. template<awaitable<Promise> Aw>
  36. Aw && await_transform(Aw && aw,
  37. const boost::source_location & loc = BOOST_CURRENT_LOCATION)
  38. {
  39. if constexpr (std::derived_from<Promise, promise_throw_if_cancelled_base>)
  40. {
  41. auto p = static_cast<Promise*>(this);
  42. // a promise inheriting promise_throw_if_cancelled_base needs to also have a .cancelled() function
  43. if (!!p->cancelled() && p->throw_if_cancelled())
  44. {
  45. constexpr boost::source_location here{BOOST_CURRENT_LOCATION};
  46. boost::throw_exception(system::system_error(
  47. {asio::error::operation_aborted, &here},
  48. "throw_if_cancelled"), loc);
  49. }
  50. }
  51. return static_cast<Aw&&>(aw);
  52. }
  53. };
  54. template <typename T>
  55. concept with_get_executor = requires (T& t)
  56. {
  57. {t.get_executor()} -> asio::execution::executor;
  58. };
  59. }
  60. #endif //BOOST_COBALT_CONCEPTS_HPP