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 2806 : blocking_context::blocking_context()
31 2806 : : impl_(new impl)
32 : {
33 2806 : }
34 :
35 2806 : blocking_context::~blocking_context()
36 : {
37 2806 : delete impl_;
38 2806 : }
39 :
40 : blocking_executor
41 2806 : blocking_context::get_executor() noexcept
42 : {
43 2806 : return blocking_executor{this};
44 : }
45 :
46 : void
47 1781 : blocking_context::signal_done() noexcept
48 : {
49 1781 : std::lock_guard<std::mutex> lock(impl_->mtx);
50 1781 : impl_->done = true;
51 1781 : impl_->cv.notify_one();
52 1781 : }
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 2798 : blocking_context::run()
66 : {
67 : for(;;)
68 : {
69 2876 : std::coroutine_handle<> h;
70 : {
71 2876 : std::unique_lock<std::mutex> lock(impl_->mtx);
72 2876 : impl_->cv.wait(lock, [&] {
73 2877 : return impl_->done || !impl_->queue.empty();
74 : });
75 2876 : if(impl_->done && impl_->queue.empty())
76 2798 : break;
77 78 : h = impl_->queue.front();
78 78 : impl_->queue.pop();
79 2876 : }
80 78 : safe_resume(h);
81 78 : }
82 2798 : if(impl_->ep)
83 1017 : std::rethrow_exception(impl_->ep);
84 1781 : }
85 :
86 : void
87 78 : blocking_context::enqueue(
88 : std::coroutine_handle<> h)
89 : {
90 78 : std::lock_guard<std::mutex> lock(impl_->mtx);
91 78 : impl_->queue.push(h);
92 78 : impl_->cv.notify_one();
93 78 : }
94 :
95 : //----------------------------------------------------------
96 :
97 : bool
98 MIS 0 : blocking_executor::operator==(
99 : blocking_executor const& other) const noexcept
100 : {
101 0 : return ctx_ == other.ctx_;
102 : }
103 :
104 : blocking_context&
105 HIT 2799 : blocking_executor::context() const noexcept
106 : {
107 2799 : return *ctx_;
108 : }
109 :
110 : void
111 2798 : blocking_executor::on_work_started() const noexcept
112 : {
113 2798 : }
114 :
115 : void
116 2798 : blocking_executor::on_work_finished() const noexcept
117 : {
118 2798 : }
119 :
120 : std::coroutine_handle<>
121 2823 : blocking_executor::dispatch(
122 : continuation& c) const
123 : {
124 2823 : return c.h;
125 : }
126 :
127 : void
128 78 : blocking_executor::post(
129 : continuation& c) const
130 : {
131 78 : ctx_->enqueue(c.h);
132 78 : }
133 :
134 : } // namespace test
135 : } // namespace capy
136 : } // namespace boost
|