thread.hpp 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  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_THREAD_HPP
  8. #define BOOST_COBALT_THREAD_HPP
  9. #include <boost/cobalt/detail/thread.hpp>
  10. #include <boost/cobalt/detail/await_result_helper.hpp>
  11. namespace boost::cobalt
  12. {
  13. // tag::outline[]
  14. struct thread
  15. {
  16. // Send a cancellation signal
  17. void cancel(asio::cancellation_type type = asio::cancellation_type::all);
  18. // Allow the thread to be awaited. NOOP if the thread is invalid.
  19. auto operator co_await() &-> detail::thread_awaitable; //<1>
  20. auto operator co_await() && -> detail::thread_awaitable; //<2>
  21. // Stops the io_context & joins the executor
  22. ~thread();
  23. /// Move constructible
  24. thread(thread &&) noexcept = default;
  25. using executor_type = executor;
  26. using id = std::thread::id;
  27. id get_id() const noexcept;
  28. // end::outline[]
  29. /* tag::outline[]
  30. // Add the functions similar to `std::thread`
  31. void join();
  32. bool joinable() const;
  33. void detach();
  34. executor_type get_executor() const;
  35. end::outline[] */
  36. BOOST_COBALT_DECL void join();
  37. BOOST_COBALT_DECL bool joinable() const;
  38. BOOST_COBALT_DECL void detach();
  39. executor_type get_executor(const boost::source_location & loc = BOOST_CURRENT_LOCATION) const
  40. {
  41. auto st = state_;
  42. if (!st || st->done)
  43. boost::throw_exception(asio::execution::bad_executor(), loc);
  44. return st ->ctx.get_executor();
  45. }
  46. using promise_type = detail::thread_promise;
  47. private:
  48. thread(std::thread thr, std::shared_ptr<detail::thread_state> state)
  49. : thread_(std::move(thr)), state_(std::move(state))
  50. {
  51. }
  52. std::thread thread_;
  53. std::shared_ptr<detail::thread_state> state_;
  54. friend struct detail::thread_promise;
  55. // tag::outline[]
  56. };
  57. // end::outline[]
  58. inline
  59. void thread::cancel(asio::cancellation_type type)
  60. {
  61. if (auto st = state_)
  62. asio::post(state_->ctx,
  63. [s= state_, type]
  64. {
  65. BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, __func__));
  66. s->signal.emit(type);
  67. });
  68. }
  69. inline
  70. auto thread::operator co_await() &-> detail::thread_awaitable
  71. {
  72. return detail::thread_awaitable{std::move(state_)};
  73. }
  74. inline
  75. auto thread::operator co_await() && -> detail::thread_awaitable
  76. {
  77. return detail::thread_awaitable{std::move(thread_), std::move(state_)};
  78. }
  79. inline
  80. thread::~thread()
  81. {
  82. if (state_)
  83. {
  84. state_->ctx.stop();
  85. state_.reset();
  86. }
  87. if (thread_.joinable())
  88. thread_.join();
  89. }
  90. inline
  91. thread::id thread::get_id() const noexcept {return thread_.get_id();}
  92. }
  93. #endif //BOOST_COBALT_THREAD_HPP