src/ex/execution_context.cpp

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