SObjectizer  5.8
Loading...
Searching...
No Matches
layer_core.cpp
Go to the documentation of this file.
1/*
2 SObjectizer 5.
3*/
4
5#include <so_5/impl/layer_core.hpp>
6
7#include <so_5/details/rollback_on_exception.hpp>
8
9#include <algorithm>
10#include <iterator>
11
12namespace so_5
13{
14
15namespace impl
16{
17
18//
19// typed_layer_ref_t
20//
21
23 :
24 m_true_type( std::type_index( typeid( int ) ) )
25{
26}
27
29 const layer_map_t::value_type & v )
30 :
33{
34}
35
37 const std::type_index & type,
38 const layer_ref_t & layer )
39 :
41 m_layer( layer )
42{
43}
44
45bool
46typed_layer_ref_t::operator < ( const typed_layer_ref_t & tl ) const
47{
48 return m_true_type < tl.m_true_type;
49}
50
51//
52// layer_core_t
53//
54
56 environment_t & env,
57 layer_map_t && so_layers )
58 :
59 m_env( env ),
61{
62 std::for_each( m_default_layers.begin(), m_default_layers.end(),
63 [this]( so_layer_list_t::value_type & item )
64 {
65 item.m_layer->bind_to_environment( &m_env );
66 } );
67
68 // The content of so_layers is no more needed.
69 so_layers.clear();
70}
71
72//! Find layer in container.
75 const so_layer_list_t & layers,
76 const std::type_index & type )
77{
78 auto search_result = std::lower_bound( layers.begin(), layers.end(),
79 type,
80 []( const so_layer_list_t::value_type & a, const std::type_index & b )
81 {
82 return a.m_true_type < b;
83 } );
84 if( search_result != layers.end() && search_result->m_true_type == type )
85 return search_result;
86
87 return layers.end();
88}
89
90layer_t *
92 const std::type_index & type ) const
93{
94 // Try search within default layers first.
95 so_layer_list_t::const_iterator layer_it = search_for_layer(
96 m_default_layers,
97 type );
98
99 if( m_default_layers.end() != layer_it )
100 return layer_it->m_layer.get();
101
102 // Layer not found yet. Search extra layers.
103 std::lock_guard< std::mutex > lock( m_extra_layers_lock );
104
105 layer_it = search_for_layer(
106 m_extra_layers,
107 type );
108
109 if( m_extra_layers.end() != layer_it )
110 return layer_it->m_layer.get();
111
112 return nullptr;
113}
114
115void
117{
118 so_layer_list_t::iterator
119 it = m_default_layers.begin(),
120 it_end = m_default_layers.end();
121
122 for(; it != it_end; ++it )
123 {
124 so_5::details::do_with_rollback_on_exception(
125 [&] { it->m_layer->start(); },
126 [&] {
127 std::for_each(
128 m_default_layers.begin(),
129 it,
130 []( typed_layer_ref_t & l ) { l.m_layer->shutdown(); } );
131
132 std::for_each(
133 m_default_layers.begin(),
134 it,
135 []( typed_layer_ref_t & l ) { l.m_layer->wait(); } );
136 } );
137 }
138}
139
140void
142{
143 // Shutdown and wait extra layers.
146
147 // Shutdown and wait default layers.
150}
151
152void
154 const std::type_index & type,
155 const layer_ref_t & layer )
156{
157 if( nullptr == layer.get() )
159 rc_trying_to_add_nullptr_extra_layer,
160 "trying to add nullptr extra layer" );
161
162 if( m_default_layers.end() != search_for_layer( m_default_layers, type ) )
164 rc_trying_to_add_extra_layer_that_already_exists_in_default_list,
165 "trying to add extra layer that already exists in default list" );
166
167 std::lock_guard< std::mutex > lock( m_extra_layers_lock );
168
169 if( m_extra_layers.end() != search_for_layer( m_extra_layers, type ) )
171 rc_trying_to_add_extra_layer_that_already_exists_in_extra_list,
172 "trying to add extra layer that already exists in extra list" );
173
174 layer->bind_to_environment( &m_env );
175
176 try
177 {
178 layer->start();
179 }
180 catch( const std::exception & x )
181 {
183 rc_unable_to_start_extra_layer,
184 std::string( "layer raised an exception: " ) + x.what() );
185 }
186
187 try
188 {
189 typed_layer_ref_t typed_layer( type, layer );
190
191 m_extra_layers.insert(
192 std::lower_bound(
193 m_extra_layers.begin(),
194 m_extra_layers.end(),
195 typed_layer ),
196 typed_layer );
197 }
198 catch( const std::exception & x )
199 {
200 // Unable to store layer. Layer must be stopped...
201 layer->shutdown();
202 layer->wait();
203
204 // ...And error must be reported.
206 rc_unable_to_start_extra_layer,
207 std::string( "unable to store pointer to layer, exception: " ) +
208 x.what() );
209 }
210}
211
212#if defined(__clang__)
213#pragma clang diagnostic push
214#pragma clang diagnostic ignored "-Wmissing-prototypes"
215#endif
216
217void
219{
220 tl.m_layer->shutdown();
221}
222void
224{
225 tl.m_layer->wait();
226}
227
228#if defined(__clang__)
229#pragma clang diagnostic pop
230#endif
231
232void
234{
235 std::for_each(
236 m_extra_layers.begin(),
237 m_extra_layers.end(),
238 call_shutdown );
239}
240
241void
243{
244 std::for_each(
245 m_extra_layers.begin(),
246 m_extra_layers.end(),
247 call_wait );
248
249 m_extra_layers.clear();
250}
251
252void
254{
255 std::for_each(
256 m_default_layers.begin(),
257 m_default_layers.end(),
258 call_shutdown );
259}
260
261void
263{
264 std::for_each(
265 m_default_layers.begin(),
266 m_default_layers.end(),
267 call_wait );
268
269}
270
271} /* namespace impl */
272
273} /* namespace so_5 */
SObjectizer Environment.
An utility class for working with layers.
void shutdown_default_layers()
Shutdown default layers.
environment_t & m_env
SObjectizer Environment to work with.
layer_t * query_layer(const std::type_index &type) const
Get a layer.
void shutdown_extra_layers()
Shutdown extra layers.
void add_extra_layer(const std::type_index &type, const layer_ref_t &layer)
Add an extra layer.
void start()
Start all layers.
layer_core_t(environment_t &env, layer_map_t &&so_layers)
void wait_extra_layers()
Blocking wait for the complete shutdown of all extra layers.
void wait_default_layers()
Blocking wait for the complete shutdown of all default layers.
void finish()
Shutdown all layers and wait for full stop of them.
An interface of the additional SObjectizer Environment layer.
Definition so_layer.hpp:31
#define SO_5_THROW_EXCEPTION(error_code, desc)
Definition exception.hpp:74
Details of SObjectizer run-time implementations.
Definition agent.cpp:905
so_layer_list_t::const_iterator search_for_layer(const so_layer_list_t &layers, const std::type_index &type)
Find layer in container.
void call_shutdown(typed_layer_ref_t &tl)
void call_wait(typed_layer_ref_t &tl)
Private part of message limit implementation.
Definition agent.cpp:33
A special wrapper to store a layer with its type.
bool operator<(const typed_layer_ref_t &tl) const
typed_layer_ref_t(const std::type_index &type, const layer_ref_t &layer)
typed_layer_ref_t(const layer_map_t::value_type &v)