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