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