thread.hpp 2.7 KB

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