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#include <boost/cobalt/thread.hpp>
9
10#include <boost/asio/append.hpp>
11#include <boost/asio/bind_executor.hpp>
12
13
14namespace boost::cobalt
15{
16
17namespace detail
18{
19
20thread_promise::thread_promise()
21 : promise_cancellation_base<asio::cancellation_slot, asio::enable_total_cancellation>(
22 signal_helper_2::signal.slot(), asio::enable_total_cancellation())
23{
24 mtx.lock();
25}
26
27void run_thread(
28 std::shared_ptr<thread_state> st_,
29 unique_handle<thread_promise> h)
30{
31
32#if !defined(BOOST_COBALT_NO_PMR)
33 pmr::unsynchronized_pool_resource resource;
34 boost::cobalt::this_thread::set_default_resource(&resource);
35 h->resource = &resource;
36#endif
37
38 {
39 auto st = std::move(st_);
40 h->reset_cancellation_source(source: st->signal.slot());
41 h->set_executor(st->ctx.get_executor());
42 boost::cobalt::this_thread::set_executor(st->ctx.get_executor());
43
44 asio::post(
45 ex: st->ctx.get_executor(),
46 token: [st, h = std::move(h)]() mutable
47 {
48 std::lock_guard<std::mutex> lock{h->mtx};
49 std::move(h).resume();
50 });
51
52 std::exception_ptr ep;
53
54 try
55 {
56 st->ctx.run();
57 }
58 catch(...)
59 {
60 ep = std::current_exception();
61 }
62
63 st->done = true;
64 st->signal.slot().clear();
65 std::lock_guard<std::mutex> lock(st->mtx);
66 if (!st->waitor && ep) // nobodies waiting, so unhandled exception
67 std::rethrow_exception(ep);
68 else if (st->waitor)
69 asio::post(token: asio::append(completion_token: *std::exchange(obj&: st->waitor, new_val: std::nullopt), values&: ep));
70 }
71}
72
73
74boost::cobalt::thread detail::thread_promise::get_return_object()
75{
76 auto st = std::make_shared<thread_state>();
77 boost::cobalt::thread res{std::thread{
78 [st,
79 h = unique_handle<detail::thread_promise>::from_promise(p&: *this)]() mutable
80 {
81 run_thread(st_: std::move(st), h: std::move(h));
82 }
83 }, st
84 };
85
86 return res;
87}
88
89
90}
91
92void thread::join() {thread_.join();}
93bool thread::joinable() const {return thread_.joinable();}
94void thread::detach()
95{
96 thread_.detach();
97 state_ = nullptr;
98}
99}

source code of boost/libs/cobalt/src/thread.cpp