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

source code of boost/libs/cobalt/include/boost/cobalt/thread.hpp