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/ex/execution_context.hpp>
11 : #include <boost/capy/ex/recycling_memory_resource.hpp>
12 : #include <boost/capy/detail/except.hpp>
13 :
14 : namespace boost {
15 : namespace capy {
16 :
17 HIT 3050 : execution_context::
18 3050 : execution_context()
19 3050 : : frame_alloc_(get_recycling_memory_resource())
20 : {
21 3050 : }
22 :
23 3050 : execution_context::
24 : ~execution_context()
25 : {
26 3050 : shutdown();
27 3050 : destroy();
28 3050 : }
29 :
30 : void
31 3218 : execution_context::
32 : shutdown() noexcept
33 : {
34 3218 : if(shutdown_)
35 168 : return;
36 3050 : shutdown_ = true;
37 :
38 3050 : service* p = head_;
39 3118 : while(p)
40 : {
41 68 : p->shutdown();
42 68 : p = p->next_;
43 : }
44 : }
45 :
46 : void
47 3218 : execution_context::
48 : destroy() noexcept
49 : {
50 3218 : service* p = head_;
51 3218 : head_ = nullptr;
52 3286 : while(p)
53 : {
54 68 : service* next = p->next_;
55 68 : delete p;
56 68 : p = next;
57 : }
58 3218 : }
59 :
60 : execution_context::service*
61 11606 : execution_context::
62 : find_impl(detail::type_index ti) const noexcept
63 : {
64 11606 : auto p = head_;
65 11615 : while(p)
66 : {
67 11465 : if(p->t0_ == ti || p->t1_ == ti)
68 11456 : break;
69 9 : p = p->next_;
70 : }
71 11606 : return p;
72 : }
73 :
74 : execution_context::service&
75 11492 : execution_context::
76 : use_service_impl(factory& f)
77 : {
78 11492 : std::unique_lock<std::mutex> lock(mutex_);
79 :
80 11492 : if(auto* p = find_impl(f.t0))
81 11431 : return *p;
82 :
83 61 : lock.unlock();
84 :
85 : // Create the service outside lock, enabling nested calls
86 61 : service* sp = f.create(*this);
87 61 : sp->t0_ = f.t0;
88 61 : sp->t1_ = f.t1;
89 :
90 61 : lock.lock();
91 :
92 61 : if(auto* p = find_impl(f.t0))
93 : {
94 1 : delete sp;
95 1 : return *p;
96 : }
97 :
98 60 : sp->next_ = head_;
99 60 : head_ = sp;
100 :
101 60 : return *sp;
102 11492 : }
103 :
104 : execution_context::service&
105 12 : execution_context::
106 : make_service_impl(factory& f)
107 : {
108 : {
109 12 : std::lock_guard<std::mutex> lock(mutex_);
110 12 : if(find_impl(f.t0))
111 2 : detail::throw_invalid_argument();
112 10 : if(f.t0 != f.t1 && find_impl(f.t1))
113 1 : detail::throw_invalid_argument();
114 12 : }
115 :
116 : // Unlocked to allow nested service creation from constructor
117 9 : service* p = f.create(*this);
118 :
119 9 : std::lock_guard<std::mutex> lock(mutex_);
120 9 : if(find_impl(f.t0))
121 : {
122 : delete p; // LCOV_EXCL_LINE concurrent same-type registration race
123 : detail::throw_invalid_argument(); // LCOV_EXCL_LINE concurrent same-type registration race
124 : }
125 :
126 9 : p->t0_ = f.t0;
127 9 : if(f.t0 != f.t1)
128 : {
129 3 : if(find_impl(f.t1))
130 : {
131 1 : delete p;
132 1 : detail::throw_invalid_argument();
133 : }
134 2 : p->t1_ = f.t1;
135 : }
136 : else
137 : {
138 6 : p->t1_ = f.t0;
139 : }
140 :
141 8 : p->next_ = head_;
142 8 : head_ = p;
143 :
144 8 : return *p;
145 9 : }
146 :
147 : } // namespace capy
148 : } // namespace boost
|