SObjectizer 5.8
Loading...
Searching...
No Matches
coop_repository_basis.cpp
Go to the documentation of this file.
1/*
2 SObjectizer 5.
3*/
4
5/*!
6 * \file
7 * \brief Basic part of coop_repository functionality.
8 *
9 * \since
10 * v.5.5.19
11 */
12#include <so_5/impl/coop_repository_basis.hpp>
13
14#include <so_5/environment.hpp>
15
16#include <so_5/details/rollback_on_exception.hpp>
17
18#include <cstdlib>
19#include <algorithm>
20
21namespace so_5
22{
23
24namespace impl
25{
26
27//
28// root_coop_t
29//
30/*!
31 * \brief A type of special coop that will be used as the root coop.
32 *
33 * \since
34 * v.5.6.0
35 */
36class coop_repository_basis_t::root_coop_t final : public coop_t
37 {
38 public :
40 coop_id_t id,
42 : coop_t{ id,
43 coop_handle_t{}, // No parent coop.
44 disp_binder_shptr_t{}, // No binder.
45 env }
46 {
47 // Automaticaly increment usage count to prevent
48 // deregistration when last child coop will be destroyed.
50
51 // Status of the coop should be changed because
52 // this coop is already "registered".
54 }
55
56 void
58 {
59 // List of children coop should be processed when
60 // the object is locked.
61 std::lock_guard< std::mutex > lock{ m_lock };
62
63 // Every child should be deregistered with 'shutdown' reason.
64 for_each_child( []( coop_t & child ) {
66 } );
67 }
68 };
69
72 coop_listener_unique_ptr_t coop_listener )
73 : m_env{ environment }
74 , m_coop_listener{ std::move(coop_listener) }
75 {
76 m_root_coop = std::make_shared< root_coop_t >(
78 m_env );
79 }
80
81[[nodiscard]]
84 coop_handle_t parent,
85 disp_binder_shptr_t default_binder )
86 {
87 if( !parent )
88 parent = m_root_coop->handle();
89
92 std::move(parent),
93 std::move(default_binder),
94 m_env );
95 }
96
97[[nodiscard]]
100 coop_unique_holder_t coop_ptr )
101 {
102 // Phase 1: check the posibility of registration of new coop.
103 // This check should be performed on locked object.
104 {
105 std::lock_guard< std::mutex > lock{ m_lock };
109 "a new coop can't be registered when shutdown "
110 "is in progress" );
111
112 // A counter of registration in progress should be incremented
113 // to prevent shutdown.
115 }
116
117 // Note: this code should be called only on locked object.
118 const auto handle_registrations_in_progress = [this]() noexcept {
119 // Decrement count of registration in progress to enable
120 // pending shutdown (if it is).
122
123 // If it was the last registration and there is a pending
124 // shutdown then we should enable shutdown procedure.
125 if( 0u == m_registrations_in_progress &&
127 {
128 m_shutdown_enabled_cond.notify_one();
129 }
130 };
131
132 // Phase 2: registration by itself.
133 coop_handle_t result;
134 try
135 {
136 // This values is necessary for updating stats if registration
137 // will be successful.
138 const auto coop_size = coop_ptr->size();
139
140 // Should be performed on unlocked object.
141 result = do_registration_specific_actions( std::move(coop_ptr) );
142
143 // Phase 3: finishing of registration.
144 // Those actions should be performed on locked objects.
146 std::lock_guard< std::mutex > lock{ m_lock };
147
148 // Statistics should be updated.
149 m_total_agents += coop_size;
150 m_total_coops += 1;
151
152 handle_registrations_in_progress();
153 } );
154 }
155 catch( ... )
156 {
157 // Pending shutdown should be handled even in the presence
158 // of an exception.
160 std::lock_guard< std::mutex > lock{ m_lock };
161
162 handle_registrations_in_progress();
163 } );
164
165 // Exception should be handled at some higher level.
166 throw;
167 }
168
169 return result;
170 }
171
174 coop_shptr_t coop ) noexcept
175 {
176 // Count of live agent and coops should be decremented.
177 {
178 std::lock_guard< std::mutex > lock{ m_lock };
179
180 m_total_agents -= coop->size();
182 }
183
184 // Coop should perform its final actions.
186
187 // Now the coop object should be released.
188 // But before that we should store some values from it
189 // to process dereg notifications.
190 const auto handle = coop->handle();
191 const auto dereg_reason =
193 const auto dereg_notificators =
195
196 // Release the coop.
197 coop.reset();
198
199 // Coop's dereg notificators can be processed now.
200 if( dereg_notificators )
201 dereg_notificators->call_all(
203 handle,
204 dereg_reason );
205
206 // Coop's listener should be notified.
207 if( m_coop_listener )
210 handle,
211 dereg_reason );
212
213 // This additional lock is necessary because a new coop
214 // can be registered while final deregistration actions
215 // were in progress.
216 return [this] {
217 std::lock_guard< std::mutex > lock{ m_lock };
218
220 // Coops those are in registration phase should also
221 // be counted as live.
224 };
225 }();
226 }
227
228void
230 {
231 // Phase 1: check that shutdown is not in progress now.
232 {
233 std::unique_lock< std::mutex > lock{ m_lock };
234
236 {
238 // NOTE: there is no need to wait on m_shutdown_enabled_cond
239 // because there is no active registration procedures.
240 }
241 else
242 {
243 // There are active registration procedures.
244 // We should wait for their completion.
246 m_shutdown_enabled_cond.wait( lock,
247 [this] { return 0 == m_registrations_in_progress; } );
249 }
250 }
251
252 // Phase 2: deregistration of all coops.
254 }
255
256[[nodiscard]]
259 {
260 std::lock_guard< std::mutex > lock{ m_lock };
261
263 {
266 }
267 else
269 }
270
276
279 {
280 std::lock_guard< std::mutex > lock{ m_lock };
281
282 return {
285 0u
286 };
287 }
288
289namespace
290{
291 /*!
292 * \since
293 * v.5.2.3
294 *
295 * \brief Special guard to increment and decrement cooperation
296 * usage counters.
297 */
314
315} /* namespace anonymous */
316
319 coop_unique_holder_t coop_ptr )
320{
321 // Cooperation object should life to the end of this routine.
322 coop_shptr_t coop{ coop_private_iface_t::make_from( std::move(coop_ptr) ) };
323
324 // This guard will guarantee, that reg_notificators for
325 // successfully registered coop will be called and completed before
326 // the dereg_notificators for that coop.
327 // Even if the coop will be deregitered while reg_notificators are
328 // still working.
329 coop_usage_counter_guard_t guard{ *coop };
330
332
333 auto result = coop->handle();
334
335 // We don't expect exceptions from the following actions.
337 // Coop's dereg notificators can be processed now.
338 auto reg_notificators =
340 if( reg_notificators )
341 reg_notificators->call_all( m_env.get(), result );
342
343 // Coop's listener should be notified.
344 if( m_coop_listener )
346 } );
347
348 return result;
349}
350
351} /* namespace impl */
352
353} /* namespace so_5 */
void call_all(environment_t &env, const coop_handle_t &coop, const coop_dereg_reason_t &reason) const noexcept
Call all notificators.
Definition coop.cpp:38
Type of smart handle for a cooperation.
bool operator!() const noexcept
Is this non-empty handle?
virtual void on_registered(environment_t &so_env, const coop_handle_t &coop) noexcept=0
Hook for the cooperation registration event.
virtual void on_deregistered(environment_t &so_env, const coop_handle_t &coop, const coop_dereg_reason_t &reason) noexcept=0
Hook for the cooperation deregistration event.
void call_all(environment_t &env, const coop_handle_t &coop) const noexcept
Call all notificators.
Definition coop.cpp:26
Agent cooperation.
Definition coop.hpp:389
registration_status_t m_registration_status
The registration status of cooperation.
Definition coop.hpp:1092
void deregister(int reason) noexcept
Deregister the cooperation with the specified reason.
Definition coop.hpp:907
void for_each_child(Lambda &&lambda) const
A helper method for doing some actions with children coops.
Definition coop.hpp:1285
std::mutex m_lock
A lock for synchonization of some operations on coop.
Definition coop.hpp:1077
registration_status_t
Registration status.
Definition coop.hpp:956
@ coop_registered
Cooperation is registered.
std::size_t size() const noexcept
Get agent count in the cooperation.
Definition coop.hpp:857
coop_handle_t handle() noexcept
Get handle for this coop.
Definition coop.hpp:432
coop_t(coop_id_t id, coop_handle_t parent, disp_binder_shptr_t coop_disp_binder, outliving_reference_t< environment_t > env)
Constructor.
Definition coop.hpp:404
A special type that plays role of unique_ptr for coop.
Definition coop.hpp:1342
coop_t * operator->() const noexcept
Definition coop.hpp:1382
An interface for environment_infrastructure entity.
SObjectizer Environment.
Special guard to increment and decrement cooperation usage counters.
A special class for accessing private members of agent_coop.
static coop_unique_holder_t make_coop(coop_id_t id, coop_handle_t parent, disp_binder_shptr_t default_binder, outliving_reference_t< environment_t > env)
static coop_reg_notificators_container_ref_t giveout_reg_notificators(coop_t &coop) noexcept
static void do_final_deregistration_actions(coop_t &coop)
static coop_dereg_reason_t dereg_reason(const coop_t &coop) noexcept
static void decrement_usage_count(coop_t &coop)
static coop_dereg_notificators_container_ref_t giveout_dereg_notificators(coop_t &coop) noexcept
static void increment_usage_count(coop_t &coop) noexcept
static void do_registration_specific_actions(coop_t &coop)
static coop_shptr_t make_from(coop_unique_holder_t holder) noexcept
root_coop_t(coop_id_t id, outliving_reference_t< environment_t > env)
A basic part for various implementations of coop_repository.
environment_t & environment()
Access to SObjectizer Environment.
std::size_t m_total_coops
Total count of coops.
std::mutex m_lock
Lock for coop repository.
coop_unique_holder_t make_coop(coop_handle_t parent, disp_binder_shptr_t default_binder)
Create an instance of a new coop.
void deregister_all_coop() noexcept
Deregisted all cooperations.
outliving_reference_t< environment_t > m_env
Environment to work in.
coop_repository_basis_t(outliving_reference_t< environment_t > environment, coop_listener_unique_ptr_t coop_listener)
std::atomic_uint_fast64_t m_coop_id_counter
Counter for coop_ids.
final_deregistration_result_t final_deregister_coop(coop_shptr_t coop) noexcept
Do final actions of the cooperation deregistration.
try_switch_to_shutdown_result_t
Result of attempt to switch to shutdown state.
coop_handle_t do_registration_specific_actions(coop_unique_holder_t coop_ptr)
An actual implementation of registration of a coop.
std::size_t m_registrations_in_progress
Count of coops those are in registration now.
environment_infrastructure_t::coop_repository_stats_t query_stats()
Get the current statistic for run-time monitoring.
status_t
Enumeration of possible repository statuses.
try_switch_to_shutdown_result_t try_switch_to_shutdown() noexcept
Try to switch repository to shutdown state.
std::shared_ptr< root_coop_t > m_root_coop
A special root coop.
coop_handle_t register_coop(coop_unique_holder_t agent_coop)
Register cooperation.
std::size_t m_total_agents
Total count of agents.
coop_listener_unique_ptr_t m_coop_listener
Cooperation actions listener.
T * operator->() const noexcept
Helper class for indication of long-lived reference via its type.
Definition outliving.hpp:98
T & get() const noexcept
outliving_reference_t(outliving_reference_t const &o) noexcept
#define SO_5_THROW_EXCEPTION(error_code, desc)
Definition exception.hpp:74
Enumeration of cooperation deregistration reasons.
Definition coop.hpp:39
const int shutdown
Deregistration because SObjectizer Environment shutdown.
Definition coop.hpp:49
Some reusable and low-level classes/functions which can be used in public header files.
auto invoke_noexcept_code(L lambda) noexcept -> decltype(lambda())
Details of SObjectizer run-time implementations.
Definition agent.cpp:780
Private part of message limit implementation.
Definition agent.cpp:33
const int rc_unable_to_register_coop_during_shutdown
It is impossible to register cooperation during SObjectizer Environment shutdown.
Definition ret_code.hpp:89
Statistical data for run-time monitoring of coop repository content.
final_deregistration_result_t(bool has_live_coop, bool total_deregistration_completed)