promise.hpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. //
  2. // Copyright (c) 2022 Klemens Morgenstern (klemens.morgenstern@gmx.net)
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. #ifndef BOOST_COBALT_PROMISE_HPP
  8. #define BOOST_COBALT_PROMISE_HPP
  9. #include <boost/cobalt/detail/promise.hpp>
  10. namespace boost::cobalt
  11. {
  12. // tag::outline[]
  13. template<typename Return>
  14. struct [[nodiscard]] promise
  15. {
  16. promise(promise &&lhs) noexcept;
  17. promise& operator=(promise && lhs) noexcept;
  18. // enable `co_await`. <1>
  19. auto operator co_await ();
  20. // Ignore the return value, i.e. detach it. <2>
  21. void operator +() &&;
  22. // Cancel the promise.
  23. void cancel(asio::cancellation_type ct = asio::cancellation_type::all);
  24. // Check if the result is ready
  25. bool ready() const;
  26. // Check if the promise can be awaited.
  27. explicit operator bool () const; // <3>
  28. // Detach or attach
  29. bool attached() const;
  30. void detach();
  31. void attach();
  32. // end::outline[]
  33. /* tag::outline[]
  34. // Create an already completed promimse
  35. static promise
  36. // Get the return value. If !ready() this function has undefined behaviour.
  37. Return get();
  38. end::outline[] */
  39. Return get(const boost::source_location & loc = BOOST_CURRENT_LOCATION)
  40. {
  41. BOOST_ASSERT(ready());
  42. return receiver_.get_result().value(loc);
  43. }
  44. using promise_type = detail::cobalt_promise<Return>;
  45. promise(const promise &) = delete;
  46. promise& operator=(const promise &) = delete;
  47. ~promise()
  48. {
  49. if (attached_)
  50. cancel();
  51. }
  52. constexpr promise(noop<Return> n) : receiver_(std::move(n)), attached_(false) {}
  53. private:
  54. template<typename>
  55. friend struct detail::cobalt_promise;
  56. promise(detail::cobalt_promise<Return> * promise) : receiver_(promise->receiver, promise->signal), attached_{true}
  57. {
  58. }
  59. detail::promise_receiver<Return> receiver_;
  60. bool attached_;
  61. friend struct detached;
  62. //tag::outline[]
  63. };
  64. // end::outline[]
  65. template<typename T>
  66. inline
  67. promise<T>::promise(promise &&lhs) noexcept
  68. : receiver_(std::move(lhs.receiver_)), attached_(std::exchange(lhs.attached_, false))
  69. {
  70. }
  71. template<typename T>
  72. inline
  73. promise<T>& promise<T>::operator=(promise && lhs) noexcept
  74. {
  75. if (attached_)
  76. cancel();
  77. receiver_ = std::move(lhs.receiver_);
  78. attached_ = std::exchange(lhs.attached_, false);
  79. return *this;
  80. }
  81. template<typename T>
  82. inline
  83. auto promise<T>::operator co_await () {return receiver_.get_awaitable();}
  84. // Ignore the returns value
  85. template<typename T>
  86. inline
  87. void promise<T>::operator +() && {detach();}
  88. template<typename T>
  89. inline
  90. void promise<T>::cancel(asio::cancellation_type ct)
  91. {
  92. if (!receiver_.done && *receiver_.reference == &receiver_)
  93. receiver_.cancel_signal->emit(ct);
  94. }
  95. template<typename T>
  96. inline
  97. bool promise<T>::ready() const { return receiver_.done; }
  98. template<typename T>
  99. inline
  100. promise<T>::operator bool () const
  101. {
  102. return !receiver_.done || !receiver_.result_taken;
  103. }
  104. template<typename T>
  105. inline
  106. bool promise<T>::attached() const {return attached_;}
  107. template<typename T>
  108. inline
  109. void promise<T>::detach() {attached_ = false;}
  110. template<typename T>
  111. inline
  112. void promise<T>::attach() {attached_ = true;}
  113. }
  114. #endif //BOOST_COBALT_PROMISE_HPP