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