TLA Line data Source code
1 : //
2 : // Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com)
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 : // Official repository: https://github.com/cppalliance/capy
8 : //
9 :
10 : #include <boost/capy/test/run_blocking.hpp>
11 :
12 : #include <boost/capy/ex/frame_allocator.hpp>
13 : #include <condition_variable>
14 : #include <mutex>
15 : #include <queue>
16 :
17 : namespace boost {
18 : namespace capy {
19 : namespace test {
20 :
21 : struct blocking_context::impl
22 : {
23 : std::mutex mtx;
24 : std::condition_variable cv;
25 : std::queue<std::coroutine_handle<>> queue;
26 : std::exception_ptr ep;
27 : bool done = false;
28 : };
29 :
30 HIT 2804 : blocking_context::blocking_context()
31 2804 : : impl_(new impl)
32 : {
33 2804 : }
34 :
35 2804 : blocking_context::~blocking_context()
36 : {
37 2804 : delete impl_;
38 2804 : }
39 :
40 : blocking_executor
41 2804 : blocking_context::get_executor() noexcept
42 : {
43 2804 : return blocking_executor{this};
44 : }
45 :
46 : void
47 1779 : blocking_context::signal_done() noexcept
48 : {
49 1779 : std::lock_guard<std::mutex> lock(impl_->mtx);
50 1779 : impl_->done = true;
51 1779 : impl_->cv.notify_one();
52 1779 : }
53 :
54 : void
55 1017 : blocking_context::signal_done(
56 : std::exception_ptr ep) noexcept
57 : {
58 1017 : std::lock_guard<std::mutex> lock(impl_->mtx);
59 1017 : impl_->ep = ep;
60 1017 : impl_->done = true;
61 1017 : impl_->cv.notify_one();
62 1017 : }
63 :
64 : void
65 2796 : blocking_context::run()
66 : {
67 : for(;;)
68 : {
69 2871 : std::coroutine_handle<> h;
70 : {
71 2871 : std::unique_lock<std::mutex> lock(impl_->mtx);
72 2871 : impl_->cv.wait(lock, [&] {
73 2871 : return impl_->done || !impl_->queue.empty();
74 : });
75 2871 : if(impl_->done && impl_->queue.empty())
76 2796 : break;
77 75 : h = impl_->queue.front();
78 75 : impl_->queue.pop();
79 2871 : }
80 75 : safe_resume(h);
81 75 : }
82 2796 : if(impl_->ep)
83 1017 : std::rethrow_exception(impl_->ep);
84 1779 : }
85 :
86 : void
87 75 : blocking_context::enqueue(
88 : std::coroutine_handle<> h)
89 : {
90 : {
91 75 : std::lock_guard<std::mutex> lock(impl_->mtx);
92 75 : impl_->queue.push(h);
93 75 : }
94 75 : impl_->cv.notify_one();
95 75 : }
96 :
97 : //----------------------------------------------------------
98 :
99 : bool
100 MIS 0 : blocking_executor::operator==(
101 : blocking_executor const& other) const noexcept
102 : {
103 0 : return ctx_ == other.ctx_;
104 : }
105 :
106 : blocking_context&
107 HIT 2796 : blocking_executor::context() const noexcept
108 : {
109 2796 : return *ctx_;
110 : }
111 :
112 : void
113 2796 : blocking_executor::on_work_started() const noexcept
114 : {
115 2796 : }
116 :
117 : void
118 2796 : blocking_executor::on_work_finished() const noexcept
119 : {
120 2796 : }
121 :
122 : std::coroutine_handle<>
123 2821 : blocking_executor::dispatch(
124 : continuation& c) const
125 : {
126 2821 : return c.h;
127 : }
128 :
129 : void
130 75 : blocking_executor::post(
131 : continuation& c) const
132 : {
133 75 : ctx_->enqueue(c.h);
134 75 : }
135 :
136 : } // namespace test
137 : } // namespace capy
138 : } // namespace boost
|