SObjectizer-5 Extra
Loading...
Searching...
No Matches
so_5_extra
shutdowner
shutdowner.hpp
Go to the documentation of this file.
1
/*!
2
* \file
3
* \brief Implementation of shutdowner-related stuff.
4
*/
5
6
#
pragma
once
7
8
#
include
<
so_5_extra
/
error_ranges
.
hpp
>
9
10
#
include
<
so_5
/
impl
/
msg_tracing_helpers
.
hpp
>
11
12
#
include
<
so_5
/
details
/
sync_helpers
.
hpp
>
13
14
#
include
<
so_5
/
mbox
.
hpp
>
15
#
include
<
so_5
/
send_functions
.
hpp
>
16
17
#
include
<
so_5
/
outliving
.
hpp
>
18
19
namespace
so_5
{
20
21
namespace
extra
{
22
23
namespace
shutdowner
{
24
25
namespace
errors
{
26
27
/*!
28
* \brief An attempt to use illegal message type.
29
*
30
* For example: shutdowner mbox allows subscription only to
31
* shutdown_initiated message.
32
*/
33
const
int
rc_illegal_msg_type
=
34
so_5
::
extra
::
errors
::
shutdowner_errors
;
35
36
/*!
37
* \brief Subscription to shutdowner mbox when shutdown in progess
38
* is prohibited.
39
*/
40
const
int
rc_subscription_disabled_during_shutdown
=
41
so_5
::
extra
::
errors
::
shutdowner_errors
+ 1;
42
43
}
/* namespace errors */
44
45
/*!
46
* \brief A message to be used to inform about start of shutdown operation.
47
*
48
* \note
49
* This is a message, not a signal. This message is empty now but it
50
* can be extended in future versions of so_5_extra.
51
*/
52
struct
shutdown_initiated_t
:
public
so_5
::
message_t
{};
53
54
namespace
details
{
55
56
/*!
57
* \brief Implementation of stop_guard for shutdowner's purposes.
58
*
59
* This implementation sends shutdown_initiated_t message to the specified
60
* mbox.
61
*/
62
class
shutdowner_guard_t
:
public
so_5
::
stop_guard_t
63
{
64
//! Mbox to which shutdown_initiated must be sent.
65
const
so_5
::
mbox_t
m_notify_mbox
;
66
67
public
:
68
//! Initializing constructor.
69
shutdowner_guard_t
( so_5::mbox_t notify_mbox )
70
:
m_notify_mbox
(
std
::
move
(
notify_mbox
) )
71
{}
72
73
virtual
void
74
stop
()
noexcept
override
75
{
76
so_5::send< shutdown_initiated_t >( m_notify_mbox );
77
}
78
};
79
80
/*!
81
* \brief A signal which is used to limit time of shutdown operation.
82
*/
83
struct
shutdown_time_elapsed_t
final
:
public
so_5::message_t {};
84
85
/*!
86
* \brief Special mbox to receive and handle a signal about time limit.
87
*
88
* This mbox implements just one method: do_deliver_message(). A std::abort()
89
* is called in this method if shutdown operation is not finished yet.
90
*/
91
class
time_elapsed_mbox_t
92
:
public
abstract_message_box_t
93
{
94
public
:
95
//! Initializing constructor.
96
time_elapsed_mbox_t
(
97
//! SObjectizer environment to work in.
98
//! It is necessary to access error_logging before calling std::abort().
99
outliving_reference_t
<
environment_t
>
env
,
100
//! Unique ID of this mbox.
101
mbox_id_t
id
)
102
:
m_env
(
env
)
103
,
m_id
(
id
)
104
{}
105
106
mbox_id_t
107
id
()
const
override
108
{
109
return
m_id
;
110
}
111
112
void
113
subscribe_event_handler
(
114
const
std
::
type_index
&
/*type_index*/
,
115
abstract_message_sink_t
&
/*subscriber*/
)
override
116
{
117
SO_5_THROW_EXCEPTION
(
rc_not_implemented
,
118
"subscribe_event_handler is not implemented for "
119
"time_elapsed_mbox"
);
120
}
121
122
void
123
unsubscribe_event_handler
(
124
const
std
::
type_index
&
/*type_index*/
,
125
abstract_message_sink_t
&
/*subscriber*/
)
noexcept
override
126
{
127
// Can't throw in noexcept method.
128
}
129
130
std
::
string
131
query_name
()
const
override
132
{
133
std
::
ostringstream
ss
;
134
ss
<<
"<mbox:type=MPSC:shutdowner_time_elapsed:id="
<<
m_id
<<
">"
;
135
return
ss
.
str
();
136
}
137
138
mbox_type_t
139
type
()
const
override
140
{
141
return
mbox_type_t
::
multi_producer_single_consumer
;
142
}
143
144
void
145
do_deliver_message
(
146
message_delivery_mode_t
/*delivery_mode*/
,
147
const
std
::
type_index
&
/*msg_type*/
,
148
const
message_ref_t
&
/*message*/
,
149
unsigned
int
/*overlimit_reaction_deep*/
)
override
150
{
151
m_env
.
get
().
error_logger
().
log
(
152
__FILE__, __LINE__,
153
"Time of shutdown operation is elapsed. "
154
"Application will be terminated."
);
155
std
::
abort
();
156
}
157
158
void
159
set_delivery_filter
(
160
const
std
::
type_index
&
/*msg_type*/
,
161
const
delivery_filter_t
&
/*filter*/
,
162
abstract_message_sink_t
&
/*subscriber*/
)
override
163
{
164
SO_5_THROW_EXCEPTION
(
rc_not_implemented
,
165
"set_delivery_filter is not implemented for "
166
"time_elapsed_mbox"
);
167
}
168
169
void
170
drop_delivery_filter
(
171
const
std
::
type_index
&
/*msg_type*/
,
172
abstract_message_sink_t
&
/*subscriber*/
)
noexcept
override
173
{
174
/* Nothing to do. */
175
}
176
177
environment_t
&
178
environment
()
const
noexcept
override
179
{
180
return
m_env
.
get
();
181
}
182
183
private
:
184
//! SOEnv to work in.
185
outliving_reference_t
<
environment_t
>
m_env
;
186
//! Unique ID of that mbox.
187
const
mbox_id_t
m_id
;
188
};
189
190
//
191
// subscriber_info_t
192
//
193
/*!
194
* \brief Description of one subscriber.
195
*/
196
struct
subscriber_info_t
197
{
198
//! Actual subscriber.
199
std
::
reference_wrapper
<
abstract_message_sink_t
>
m_sink
;
200
//! Message limit for that subscriber.
201
202
//! Initializing constructor.
203
subscriber_info_t
(
204
abstract_message_sink_t & sink )
205
:
m_sink
(
sink
)
206
{}
207
208
//! Comparison operator.
209
/*!
210
* Compares only pointers to m_subscriber with respects
211
* to agent's priority.
212
*/
213
bool
214
operator
<(
const
subscriber_info_t
& o )
const
215
{
216
return
abstract_message_sink_t::special_sink_ptr_compare(
217
std::addressof(
this
->m_sink.get() ),
218
std::addressof( o.m_sink.get() ) );
219
}
220
};
221
222
//
223
// subscriber_container_t
224
//
225
/*!
226
* \brief Type of subscriber's container.
227
*/
228
using
subscriber_container_t
=
std
::
vector
<
subscriber_info_t
>;
229
230
namespace
status
{
231
232
//! Avaliable statuses of shutdown operation.
233
enum
class
value_t
234
{
235
//! Shutdown is not started yet.
236
not_started
,
237
//! Shutdown is started but there are some pending subscribers.
238
started
,
239
//! All subscribers are unsubscribed.
240
//! Shutdown can and should be completed.
241
must_be_completed
242
};
243
244
constexpr
const
value_t
not_started
=
value_t
::
not_started
;
245
constexpr
const
value_t
started
=
value_t
::
started
;
246
constexpr
const
value_t
must_be_completed
=
value_t
::
must_be_completed
;
247
248
//! Which action must be performed after updating status of shutdown operation.
249
enum
class
deferred_action_t
250
{
251
//! No action is required.
252
do_nothing
,
253
//! Shutdown action must be completed.
254
complete_shutdown
255
};
256
257
//! Special object which holds status.
258
/*!
259
* Updates for the status are enabled only to instances of updater_t class.
260
*/
261
class
holder_t
262
{
263
friend
class
updater_t
;
264
265
value_t
m_status
=
value_t
::
not_started
;
266
267
public
:
268
value_t
269
current
()
const
noexcept
{
return
m_status
; }
270
};
271
272
//! Special object to change the status and detect deferred action to be performed.
273
class
updater_t
274
{
275
outliving_reference_t
<
holder_t
>
m_status
;
276
deferred_action_t
m_action
=
deferred_action_t
::
do_nothing
;
277
278
public
:
279
updater_t
(
280
outliving_reference_t< holder_t > status )
281
:
m_status
(
status
)
282
{}
283
284
value_t
285
current
()
const
noexcept
{
return
m_status
.
get
().
current
(); }
286
287
void
288
update
(
value_t
new_status
)
noexcept
289
{
290
m_status
.
get
().
m_status
=
new_status
;
291
if
(
value_t
::
must_be_completed
==
new_status
)
292
m_action
=
deferred_action_t
::
complete_shutdown
;
293
else
294
m_action
=
deferred_action_t
::
do_nothing
;
295
}
296
297
deferred_action_t
298
action
()
const
noexcept
{
return
m_action
; }
299
};
300
301
}
/* namespace status */
302
303
//
304
// notify_mbox_data_t
305
//
306
/*!
307
* \brief An internal data of notify_mbox.
308
*
309
* It is collected in separate struct to provide ability to mark
310
* object of that struct as mutable. It is necessary because some
311
* of abstract_message_box_t's methods are declared as const by
312
* historical reasons.
313
*/
314
struct
notify_mbox_data_t
315
{
316
//! Status of the shutdown operation.
317
status
::
holder_t
m_status
;
318
319
//! List of actual subscribers.
320
subscriber_container_t
m_subscribers
;
321
322
//! Mbox to be used for delayed shutdown_time_elapsed message.
323
mbox_t
m_time_elapsed_mbox
;
324
//! A time for shutdown operation.
325
const
std
::
chrono
::
steady_clock
::
duration
m_max_shutdown_time
;
326
327
//! Timer ID for shutdown_time_elapsed message.
328
/*!
329
* Will be used for canceling of delayed message when shutdown is
330
* completed.
331
*
332
* Will receive actual value only when shutdown operation started.
333
*/
334
timer_id_t
m_shutdown_timer
;
335
336
//! Initializing constructor.
337
notify_mbox_data_t
(
338
mbox_t time_elapsed_mbox,
339
std::chrono::steady_clock::duration max_shutdown_time )
340
:
m_time_elapsed_mbox
(
std
::
move
(
time_elapsed_mbox
) )
341
,
m_max_shutdown_time
(
max_shutdown_time
)
342
{}
343
};
344
345
//
346
// notify_mbox_t
347
//
348
/*!
349
* \brief A special mbox which must be used for notification about
350
* shutdown operation.
351
*
352
* \tparam Lock_Type type of lock to be used for thread safety
353
* \tparam Tracing_Base type that implements message tracing stuff
354
* It is expected to be so_5::impl::msg_tracing_helpers::tracing_enabled_base
355
* or so_5::impl::msg_tracing_helpers::tracing_disabled_base
356
*/
357
template
<
typename
Lock_Type,
typename
Tracing_Base >
358
class
notify_mbox_t
359
:
public
abstract_message_box_t
360
,
private
::
so_5
::
details
::
lock_holder_detector
<
Lock_Type
>::
type
361
,
private
Tracing_Base
362
{
363
public
:
364
template
<
typename
... Tracing_Base_Args >
365
notify_mbox_t
(
366
//! SObjectizer Environment to work in.
367
outliving_reference_t
<
environment_t
>
env
,
368
//! A mbox for delayed message shutdown_time_elapsed_t.
369
mbox_t
time_elapsed_mbox
,
370
//! Time for the whole shutdown operation.
371
std
::
chrono
::
steady_clock
::
duration
max_shutdown_time
,
372
//! Unique ID of that mbox.
373
mbox_id_t
id
,
374
//! Params for tracing stuff.
375
Tracing_Base_Args
&& ...
tracing_args
)
376
:
Tracing_Base
(
std
::
forward
<
Tracing_Base_Args
>(
tracing_args
)... )
377
,
m_env
(
env
)
378
, m_id( id )
379
, m_data( std::move(time_elapsed_mbox), max_shutdown_time )
380
{
381
// Now we can create and install shutdowner_guard to
382
// prevent SObjectizer from shutdown.
383
auto
guard
=
std
::
make_shared
<
shutdowner_guard_t
>(
mbox_t
(
this
) );
384
m_env
.
get
().
setup_stop_guard
(
guard
);
385
m_shutdowner_guard
=
std
::
move
(
guard
);
386
}
387
388
mbox_id_t
389
id
()
const
override
390
{
391
return
m_id
;
392
}
393
394
void
395
subscribe_event_handler
(
396
const
std
::
type_index
&
type_index
,
397
abstract_message_sink_t
&
subscriber
)
override
398
{
399
ensure_valid_message_type
(
type_index
);
400
this
->
lock_and_perform
( [&] {
401
do_event_subscription
(
subscriber
);
402
} );
403
}
404
405
void
406
unsubscribe_event_handler
(
407
const
std
::
type_index
&
type_index
,
408
abstract_message_sink_t
&
subscriber
)
noexcept
override
409
{
410
ensure_valid_message_type
(
type_index
);
411
const
auto
action
=
this
->
lock_and_perform
( [&] {
412
return
do_event_unsubscripton
(
subscriber
);
413
} );
414
415
if
(
status
::
deferred_action_t
::
complete_shutdown
==
action
)
416
complete_shutdown
();
417
}
418
419
std
::
string
420
query_name
()
const
override
421
{
422
std
::
ostringstream
ss
;
423
ss
<<
"<mbox:type=MPMC:shutdowner:id="
<<
m_id
<<
">"
;
424
return
ss
.
str
();
425
}
426
427
mbox_type_t
428
type
()
const
override
429
{
430
return
mbox_type_t
::
multi_producer_multi_consumer
;
431
}
432
433
void
434
do_deliver_message
(
435
message_delivery_mode_t
delivery_mode
,
436
const
std
::
type_index
&
msg_type
,
437
const
message_ref_t
&
message
,
438
unsigned
int
/*overlimit_reaction_deep*/
)
override
439
{
440
ensure_valid_message_type
(
msg_type
);
441
const
auto
action
=
do_initiate_shutdown
(
442
delivery_mode
,
msg_type
,
message
);
443
if
(
status
::
deferred_action_t
::
complete_shutdown
==
action
)
444
complete_shutdown
();
445
}
446
447
void
448
set_delivery_filter
(
449
const
std
::
type_index
&
msg_type
,
450
const
delivery_filter_t
&
/*filter*/
,
451
abstract_message_sink_t
&
/*subscriber*/
)
override
452
{
453
ensure_valid_message_type
(
msg_type
);
454
SO_5_THROW_EXCEPTION
(
rc_not_implemented
,
455
"unable to set delivery filter to shutdowner mbox"
);
456
}
457
458
void
459
drop_delivery_filter
(
460
const
std
::
type_index
&
/*msg_type*/
,
461
abstract_message_sink_t
&
/*subscriber*/
)
noexcept
override
462
{
463
/* Nothing to do. */
464
}
465
466
environment_t
&
467
environment
()
const
noexcept
override
468
{
469
return
m_env
.
get
();
470
}
471
472
private
:
473
//! SObjectizer Environment to work in.
474
outliving_reference_t
<
environment_t
>
m_env
;
475
476
//! Stop_guard which prevents SObjectizer from shutdown.
477
stop_guard_shptr_t
m_shutdowner_guard
;
478
479
//! Unique ID of that mbox.
480
const
mbox_id_t
m_id
;
481
482
//! Actual mbox data.
483
notify_mbox_data_t
m_data
;
484
485
//! Check for valid type of message to be handled.
486
/*!
487
* \note
488
* Only shutdown_initiated_t message can be handled by that mbox type.
489
*/
490
static
void
491
ensure_valid_message_type
(
const
std::type_index & type_index )
492
{
493
if
(
type_index
!=
typeid
(
shutdown_initiated_t
) )
494
SO_5_THROW_EXCEPTION
(
495
::
so_5
::
extra
::
shutdowner
::
errors
::
rc_illegal_msg_type
,
496
"only shutdown_initiated_t message type is allowed to "
497
"be used with shutdowner mbox"
);
498
}
499
500
//! Main subscription actions.
501
/*!
502
* May throw if shutdown is in progress or already completed.
503
*/
504
void
505
do_event_subscription
(
506
abstract_message_sink_t & subscriber )
507
{
508
if
(
status
::
not_started
!=
m_data
.
m_status
.
current
() )
509
SO_5_THROW_EXCEPTION
(
510
::
so_5
::
extra
::
shutdowner
::
errors
::
rc_subscription_disabled_during_shutdown
,
511
"a creation of new subscription is disabled during "
512
"shutdown procedure"
);
513
514
subscriber_info_t
info
{
subscriber
};
515
auto
it
=
std
::
lower_bound
(
516
std
::
begin
(
m_data
.
m_subscribers
),
517
std
::
end
(
m_data
.
m_subscribers
),
518
info
);
519
m_data
.
m_subscribers
.
insert
(
it
,
info
);
520
}
521
522
//! Main unsubscription actions.
523
/*!
524
* Returns the action to be performed (shutdown completion may be
525
* necessary).
526
*/
527
status
::
deferred_action_t
528
do_event_unsubscripton
(
529
abstract_message_sink_t & subscriber )
530
{
531
status
::
updater_t
status_updater
(
532
outliving_mutable
(
m_data
.
m_status
) );
533
534
subscriber_info_t
info
{
subscriber
};
535
auto
it
=
std
::
lower_bound
(
536
std
::
begin
(
m_data
.
m_subscribers
),
537
std
::
end
(
m_data
.
m_subscribers
),
538
info
);
539
if
(
it
!=
std
::
end
(
m_data
.
m_subscribers
) &&
540
std
::
addressof
(
it
->
m_sink
.
get
()) ==
std
::
addressof
(
subscriber
) )
541
{
542
m_data
.
m_subscribers
.
erase
(
it
);
543
544
if
(
status
::
started
==
status_updater
.
current
() )
545
{
546
if
(
m_data
.
m_subscribers
.
empty
() )
547
{
548
status_updater
.
update
(
549
status
::
must_be_completed
);
550
}
551
}
552
}
553
554
return
status_updater
.
action
();
555
}
556
557
//! Do all necessary actions for completion of shutdown.
558
void
559
complete_shutdown
()
560
{
561
m_data
.
m_shutdown_timer
.
release
();
562
563
m_env
.
get
().
remove_stop_guard
(
m_shutdowner_guard
);
564
}
565
566
//! Do all necessary actions for start of shutdown operation.
567
/*!
568
* Returns the action to be performed (shutdown completion may be
569
* necessary).
570
*/
571
status
::
deferred_action_t
572
do_initiate_shutdown
(
573
message_delivery_mode_t delivery_mode,
574
const
std::type_index & msg_type,
575
const
message_ref_t & message )
576
{
577
status
::
updater_t
updater
(
578
outliving_mutable
(
m_data
.
m_status
) );
579
580
if
(
status
::
not_started
==
updater
.
current
() )
581
{
582
updater
.
update
(
status
::
started
);
583
if
( !
m_data
.
m_subscribers
.
empty
() )
584
{
585
send_shutdown_initated_to_all
(
586
delivery_mode
,
msg_type
,
message
);
587
start_shutdown_clock
();
588
}
589
else
590
{
591
updater
.
update
(
status
::
must_be_completed
);
592
}
593
}
594
595
return
updater
.
action
();
596
}
597
598
//! Send shutdown_initiated message to all actual subscribers.
599
void
600
send_shutdown_initated_to_all
(
601
message_delivery_mode_t delivery_mode,
602
const
std::type_index & msg_type,
603
const
message_ref_t & message )
604
{
605
constexpr
unsigned
int
redirection_deep
= 0u;
606
607
typename
Tracing_Base
::
deliver_op_tracer
tracer
{
608
*
this
,
// as Tracing_Base
609
*
this
,
// as abstract_message_box_t
610
"deliver_message"
,
611
delivery_mode
,
612
msg_type
,
message
,
redirection_deep
};
613
614
for
(
const
auto
&
subscriber
:
m_data
.
m_subscribers
)
615
{
616
subscriber
.
m_sink
.
get
().
push_event
(
617
this
->
id
(),
618
delivery_mode
,
619
msg_type
,
620
message
,
621
redirection_deep
,
622
tracer
.
overlimit_tracer
() );
623
}
624
}
625
626
//! Initiate delayed shutdown_time_elapsed message.
627
void
628
start_shutdown_clock
()
629
{
630
m_data
.
m_shutdown_timer
=
so_5
::
send_periodic
<
shutdown_time_elapsed_t
>(
631
m_data
.
m_time_elapsed_mbox
,
632
m_data
.
m_max_shutdown_time
,
633
std
::
chrono
::
milliseconds
::
zero
() );
634
}
635
};
636
637
}
/* namespace details */
638
639
//
640
// layer_t
641
//
642
/*!
643
* \brief An interface of shutdowner layer.
644
*
645
* This is a public interface of actual layer. An user should use only
646
* that interface when it want to work with shutdown layer.
647
*
648
* For example, to subscribe to shutdown_initiated_t message it is neccessary
649
* to receive a pointer/reference to layer_t and call notify_mbox() method:
650
* \code
651
* // To make a subscription to shutdown notification.
652
* class my_agent final : public so_5::agent_t {
653
* public :
654
* my_agent(context_t ctx) : so_5::agent_t(std::move(ctx)) {
655
* // Long way:
656
* so_5::extra::shutdowner::layer_t * s =
657
* so_environment().query_layer<so_5::extra::shutdowner::layer_t>();
658
* so_subscribe(s->notify_mbox()).event(&my_agent::on_shutdown);
659
*
660
* // Shortest way:
661
* so_subscribe(so_5::extra::shutdowner::layer(so_environment()).notify_mbox())
662
* .event(&my_agent::on_shutdown);
663
* ...
664
* }
665
* ...
666
* private :
667
* void on_shutdown(mhood_t<so_5::extra::shutdowner::shutdown_initiated_t>)
668
* {...}
669
* };
670
* \endcode
671
*
672
* To initiate shutdown it is necessary to call so_5::environment_t::stop()
673
* method:
674
* \code
675
* so_environment().stop();
676
* \endcode
677
*/
678
class
layer_t
:
public
::
so_5
::
layer_t
679
{
680
public
:
681
//! Get a mbox which can be used for subscription to
682
//! shutdown_initiated message.
683
virtual
mbox_t
684
notify_mbox
()
const
= 0;
685
};
686
687
namespace
details
{
688
689
//
690
// layer_template_t
691
//
692
/*!
693
* \brief A template-based implementation of shutdowner layer.
694
*
695
* \note
696
* It creates all shutdowner-related stuff in start() method.
697
*/
698
template
<
typename
Lock_Type >
699
class
layer_template_t
:
public
::
so_5
::
extra
::
shutdowner
::
layer_t
700
{
701
public
:
702
//! Initializing constructor.
703
layer_template_t
(
704
//! Maximum time for the shutdown operation.
705
std::chrono::steady_clock::duration shutdown_time )
706
:
m_shutdown_time
(
shutdown_time
)
707
{}
708
709
virtual
mbox_t
710
notify_mbox
()
const
override
711
{
712
return
m_notify_mbox
;
713
}
714
715
virtual
void
716
start
()
override
717
{
718
auto
time_elapsed_mbox
=
so_environment
().
make_custom_mbox
(
719
[&](
const
mbox_creation_data_t
&
data
) {
720
return
do_make_time_elapsed_mbox
(
data
);
721
} );
722
723
m_notify_mbox
=
so_environment
().
make_custom_mbox
(
724
[&](
const
mbox_creation_data_t
&
data
) {
725
return
do_make_notification_mbox
(
726
data
,
727
std
::
move
(
time_elapsed_mbox
) );
728
} );
729
}
730
731
private
:
732
//! Maximum time for the shutdown operation.
733
const
std
::
chrono
::
steady_clock
::
duration
m_shutdown_time
;
734
735
//! Notification mbox.
736
/*!
737
* Will be created in start() method. Until then it is a null pointer.
738
*/
739
mbox_t
m_notify_mbox
;
740
741
//! Create mbox for delayed shutdown_time_elapsed message.
742
mbox_t
743
do_make_time_elapsed_mbox
(
744
//! Parameters for the new mbox.
745
const
mbox_creation_data_t
&
data
)
746
{
747
return
mbox_t
(
new
details
::
time_elapsed_mbox_t
(
748
outliving_mutable
(
so_environment
() ),
749
data
.
m_id
) );
750
}
751
752
//! Create notification mbox.
753
/*!
754
* A new mbox will be created with respect to message tracing stuff.
755
*/
756
mbox_t
757
do_make_notification_mbox
(
758
//! Parameters for the new mbox.
759
const
mbox_creation_data_t
&
data
,
760
//! A mbox to be used for delayed shutdown_time_elapsed message.
761
mbox_t
time_elapsed_mbox
)
762
{
763
mbox_t
result
;
764
765
if
(
data
.
m_tracer
.
get
().
is_msg_tracing_enabled
() )
766
{
767
using
T
=
details
::
notify_mbox_t
<
768
Lock_Type
,
769
::
so_5
::
impl
::
msg_tracing_helpers
::
tracing_enabled_base
>;
770
result
=
mbox_t
(
new
T
(
771
outliving_mutable
(
so_environment
() ),
772
std
::
move
(
time_elapsed_mbox
),
773
m_shutdown_time
,
774
data
.
m_id
,
775
data
.
m_tracer
) );
776
}
777
else
778
{
779
using
T
=
details
::
notify_mbox_t
<
780
Lock_Type
,
781
::
so_5
::
impl
::
msg_tracing_helpers
::
tracing_disabled_base
>;
782
result
=
mbox_t
(
new
T
(
783
outliving_mutable
(
so_environment
() ),
784
std
::
move
(
time_elapsed_mbox
),
785
m_shutdown_time
,
786
data
.
m_id
) );
787
}
788
789
return
result
;
790
}
791
};
792
793
}
/* namespace details */
794
795
//
796
// make_layer
797
//
798
/*!
799
* \brief Main function to create an instance of shutdowner layer.
800
*
801
* Usage example:
802
* \code
803
* // Creation of layer with default mutex type.
804
* so_5::launch([](so_5::environment_t & env) {...},
805
* [](so_5::environment_params_t & params) {
806
* params.add_layer( so_5::extra::shutdowner::make_layer<>(30s) );
807
* });
808
*
809
* // Creation of layer with user-provided spinlock type.
810
* so_5::launch([](so_5::environment_t & env) {...},
811
* [](so_5::environment_params_t & params) {
812
* params.add_layer( so_5::extra::shutdowner::make_layer<my_spinlock_t>(30s));
813
* });
814
*
815
* // Creation of layer with null_mutex.
816
* // Note: null_mutex must be used only for non thread-safe environments.
817
* so_5::launch([](so_5::environment_t & env) {...},
818
* [](so_5::environment_params_t & params) {
819
* // Use single-threaded and not thread-safe environment.
820
* params.infrastructure_factory(
821
* so_5::env_infrastructures::simple_not_mtsafe::factory());
822
* // Shutdowner layer with null_mutex can be used in that environment.
823
* params.add_layer( so_5::extra::shutdowner::make_layer<so_5::null_mutex_t>(30s));
824
* });
825
* \endcode
826
*
827
* \tparam Lock_Type type of lock to be used for thread safety.
828
*/
829
template
<
typename
Lock_Type =
std
::
mutex
>
830
std
::
unique_ptr
< ::
so_5
::
extra
::
shutdowner
::
layer_t
>
831
make_layer
(
832
//! A maximum time for timeout operation.
833
std
::
chrono
::
steady_clock
::
duration
shutdown_max_time
)
834
{
835
std
::
unique_ptr
< ::
so_5
::
extra
::
shutdowner
::
layer_t
>
result
(
836
new
details
::
layer_template_t
<
Lock_Type
>(
837
shutdown_max_time
) );
838
839
return
result
;
840
}
841
842
//
843
// layer
844
//
845
/*!
846
* \brief A helper function to receive a reference to shutdowner layer.
847
*
848
* Usage example:
849
* \code
850
* // To make a subscription to shutdown notification.
851
* class my_agent final : public so_5::agent_t {
852
* public :
853
* my_agent(context_t ctx) : so_5::agent_t(std::move(ctx)) {
854
* auto & s = so_5::extra::shutdowner::layer( so_environment() );
855
* so_subscribe( s.notify_mbox() ).event( &my_agent::on_shutdown );
856
* ...
857
* }
858
* ...
859
* private :
860
* void on_shutdown(mhood_t<so_5::extra::shutdowner::shutdown_initiated_t>)
861
* {...}
862
* };
863
*
864
* // To initiate shutdown.
865
* so_5::extra::shutdowner::layer(env).initiate_shutdown();
866
* \endcode
867
*
868
* \note May throw an exception if shutdowner layer is not defined.
869
*/
870
inline
::
so_5
::
extra
::
shutdowner
::
layer_t
&
871
layer
( ::so_5::environment_t & env )
872
{
873
return
*(env.query_layer< ::so_5::extra::shutdowner::layer_t >());
874
}
875
876
}
/* namespace shutdowner */
877
878
}
/* namespace extra */
879
880
}
/* namespace so_5 */
so_5::extra::shutdowner::details::layer_template_t
A template-based implementation of shutdowner layer.
Definition
shutdowner.hpp:700
so_5::extra::shutdowner::details::layer_template_t::do_make_time_elapsed_mbox
mbox_t do_make_time_elapsed_mbox(const mbox_creation_data_t &data)
Create mbox for delayed shutdown_time_elapsed message.
Definition
shutdowner.hpp:743
so_5::extra::shutdowner::details::layer_template_t::layer_template_t
layer_template_t(std::chrono::steady_clock::duration shutdown_time)
Initializing constructor.
Definition
shutdowner.hpp:703
so_5::extra::shutdowner::details::layer_template_t::m_shutdown_time
const std::chrono::steady_clock::duration m_shutdown_time
Maximum time for the shutdown operation.
Definition
shutdowner.hpp:733
so_5::extra::shutdowner::details::layer_template_t::notify_mbox
virtual mbox_t notify_mbox() const override
Get a mbox which can be used for subscription to shutdown_initiated message.
Definition
shutdowner.hpp:710
so_5::extra::shutdowner::details::layer_template_t::m_notify_mbox
mbox_t m_notify_mbox
Notification mbox.
Definition
shutdowner.hpp:739
so_5::extra::shutdowner::details::layer_template_t::do_make_notification_mbox
mbox_t do_make_notification_mbox(const mbox_creation_data_t &data, mbox_t time_elapsed_mbox)
Create notification mbox.
Definition
shutdowner.hpp:757
so_5::extra::shutdowner::details::layer_template_t::start
virtual void start() override
Definition
shutdowner.hpp:716
so_5::extra::shutdowner::details::notify_mbox_t
A special mbox which must be used for notification about shutdown operation.
Definition
shutdowner.hpp:362
so_5::extra::shutdowner::details::notify_mbox_t::m_shutdowner_guard
stop_guard_shptr_t m_shutdowner_guard
Stop_guard which prevents SObjectizer from shutdown.
Definition
shutdowner.hpp:477
so_5::extra::shutdowner::details::notify_mbox_t::ensure_valid_message_type
static void ensure_valid_message_type(const std::type_index &type_index)
Check for valid type of message to be handled.
Definition
shutdowner.hpp:491
so_5::extra::shutdowner::details::notify_mbox_t::notify_mbox_t
notify_mbox_t(outliving_reference_t< environment_t > env, mbox_t time_elapsed_mbox, std::chrono::steady_clock::duration max_shutdown_time, mbox_id_t id, Tracing_Base_Args &&...tracing_args)
Definition
shutdowner.hpp:365
so_5::extra::shutdowner::details::notify_mbox_t::send_shutdown_initated_to_all
void send_shutdown_initated_to_all(message_delivery_mode_t delivery_mode, const std::type_index &msg_type, const message_ref_t &message)
Send shutdown_initiated message to all actual subscribers.
Definition
shutdowner.hpp:600
so_5::extra::shutdowner::details::notify_mbox_t::do_event_unsubscripton
status::deferred_action_t do_event_unsubscripton(abstract_message_sink_t &subscriber)
Main unsubscription actions.
Definition
shutdowner.hpp:528
so_5::extra::shutdowner::details::notify_mbox_t::do_event_subscription
void do_event_subscription(abstract_message_sink_t &subscriber)
Main subscription actions.
Definition
shutdowner.hpp:505
so_5::extra::shutdowner::details::notify_mbox_t::complete_shutdown
void complete_shutdown()
Do all necessary actions for completion of shutdown.
Definition
shutdowner.hpp:559
so_5::extra::shutdowner::details::notify_mbox_t::start_shutdown_clock
void start_shutdown_clock()
Initiate delayed shutdown_time_elapsed message.
Definition
shutdowner.hpp:628
so_5::extra::shutdowner::details::notify_mbox_t::do_initiate_shutdown
status::deferred_action_t do_initiate_shutdown(message_delivery_mode_t delivery_mode, const std::type_index &msg_type, const message_ref_t &message)
Do all necessary actions for start of shutdown operation.
Definition
shutdowner.hpp:572
so_5::extra::shutdowner::details::shutdowner_guard_t
Implementation of stop_guard for shutdowner's purposes.
Definition
shutdowner.hpp:63
so_5::extra::shutdowner::details::shutdowner_guard_t::stop
virtual void stop() noexcept override
Definition
shutdowner.hpp:74
so_5::extra::shutdowner::details::shutdowner_guard_t::m_notify_mbox
const so_5::mbox_t m_notify_mbox
Mbox to which shutdown_initiated must be sent.
Definition
shutdowner.hpp:65
so_5::extra::shutdowner::details::shutdowner_guard_t::shutdowner_guard_t
shutdowner_guard_t(so_5::mbox_t notify_mbox)
Initializing constructor.
Definition
shutdowner.hpp:69
so_5::extra::shutdowner::details::status::holder_t
Special object which holds status.
Definition
shutdowner.hpp:262
so_5::extra::shutdowner::details::status::holder_t::m_status
value_t m_status
Definition
shutdowner.hpp:265
so_5::extra::shutdowner::details::status::holder_t::current
value_t current() const noexcept
Definition
shutdowner.hpp:269
so_5::extra::shutdowner::details::status::updater_t
Special object to change the status and detect deferred action to be performed.
Definition
shutdowner.hpp:274
so_5::extra::shutdowner::details::status::updater_t::m_action
deferred_action_t m_action
Definition
shutdowner.hpp:276
so_5::extra::shutdowner::details::status::updater_t::m_status
outliving_reference_t< holder_t > m_status
Definition
shutdowner.hpp:275
so_5::extra::shutdowner::details::time_elapsed_mbox_t
Special mbox to receive and handle a signal about time limit.
Definition
shutdowner.hpp:93
so_5::extra::shutdowner::details::time_elapsed_mbox_t::time_elapsed_mbox_t
time_elapsed_mbox_t(outliving_reference_t< environment_t > env, mbox_id_t id)
Initializing constructor.
Definition
shutdowner.hpp:96
so_5::extra::shutdowner::layer_t
An interface of shutdowner layer.
Definition
shutdowner.hpp:679
so_5::extra::shutdowner::layer_t::notify_mbox
virtual mbox_t notify_mbox() const =0
Get a mbox which can be used for subscription to shutdown_initiated message.
so_5::extra::errors
Definition
error_ranges.hpp:13
so_5::extra::errors::shutdowner_errors
const int shutdowner_errors
Starting point for errors of shutdowner submodule.
Definition
error_ranges.hpp:16
so_5::extra::shutdowner::details::status
Definition
shutdowner.hpp:230
so_5::extra::shutdowner::details::status::deferred_action_t
deferred_action_t
Which action must be performed after updating status of shutdown operation.
Definition
shutdowner.hpp:250
so_5::extra::shutdowner::details::status::deferred_action_t::complete_shutdown
@ complete_shutdown
Shutdown action must be completed.
so_5::extra::shutdowner::details::status::deferred_action_t::do_nothing
@ do_nothing
No action is required.
so_5::extra::shutdowner::details::status::started
constexpr const value_t started
Definition
shutdowner.hpp:245
so_5::extra::shutdowner::details::status::not_started
constexpr const value_t not_started
Definition
shutdowner.hpp:244
so_5::extra::shutdowner::details::status::must_be_completed
constexpr const value_t must_be_completed
Definition
shutdowner.hpp:246
so_5::extra::shutdowner::details::status::value_t
value_t
Avaliable statuses of shutdown operation.
Definition
shutdowner.hpp:234
so_5::extra::shutdowner::details::status::value_t::must_be_completed
@ must_be_completed
All subscribers are unsubscribed. Shutdown can and should be completed.
so_5::extra::shutdowner::details::status::value_t::started
@ started
Shutdown is started but there are some pending subscribers.
so_5::extra::shutdowner::details::status::value_t::not_started
@ not_started
Shutdown is not started yet.
so_5::extra::shutdowner::details
Definition
shutdowner.hpp:54
so_5::extra::shutdowner::errors
Definition
shutdowner.hpp:25
so_5::extra::shutdowner::errors::rc_subscription_disabled_during_shutdown
const int rc_subscription_disabled_during_shutdown
Subscription to shutdowner mbox when shutdown in progess is prohibited.
Definition
shutdowner.hpp:40
so_5::extra::shutdowner::errors::rc_illegal_msg_type
const int rc_illegal_msg_type
An attempt to use illegal message type.
Definition
shutdowner.hpp:33
so_5::extra::shutdowner
Definition
shutdowner.hpp:23
so_5::extra::shutdowner::make_layer
std::unique_ptr< ::so_5::extra::shutdowner::layer_t > make_layer(std::chrono::steady_clock::duration shutdown_max_time)
Main function to create an instance of shutdowner layer.
Definition
shutdowner.hpp:831
so_5::extra::shutdowner::layer
inline ::so_5::extra::shutdowner::layer_t & layer(::so_5::environment_t &env)
A helper function to receive a reference to shutdowner layer.
Definition
shutdowner.hpp:871
so_5::extra
Definition
details.hpp:15
so_5
Ranges for error codes of each submodules.
Definition
details.hpp:13
so_5::extra::shutdowner::details::notify_mbox_data_t
An internal data of notify_mbox.
Definition
shutdowner.hpp:315
so_5::extra::shutdowner::details::notify_mbox_data_t::m_status
status::holder_t m_status
Status of the shutdown operation.
Definition
shutdowner.hpp:317
so_5::extra::shutdowner::details::notify_mbox_data_t::notify_mbox_data_t
notify_mbox_data_t(mbox_t time_elapsed_mbox, std::chrono::steady_clock::duration max_shutdown_time)
Initializing constructor.
Definition
shutdowner.hpp:337
so_5::extra::shutdowner::details::notify_mbox_data_t::m_time_elapsed_mbox
mbox_t m_time_elapsed_mbox
Mbox to be used for delayed shutdown_time_elapsed message.
Definition
shutdowner.hpp:323
so_5::extra::shutdowner::details::notify_mbox_data_t::m_shutdown_timer
timer_id_t m_shutdown_timer
Timer ID for shutdown_time_elapsed message.
Definition
shutdowner.hpp:334
so_5::extra::shutdowner::details::notify_mbox_data_t::m_max_shutdown_time
const std::chrono::steady_clock::duration m_max_shutdown_time
A time for shutdown operation.
Definition
shutdowner.hpp:325
so_5::extra::shutdowner::details::notify_mbox_data_t::m_subscribers
subscriber_container_t m_subscribers
List of actual subscribers.
Definition
shutdowner.hpp:320
so_5::extra::shutdowner::details::subscriber_info_t
Description of one subscriber.
Definition
shutdowner.hpp:197
so_5::extra::shutdowner::details::subscriber_info_t::operator<
bool operator<(const subscriber_info_t &o) const
Comparison operator.
Definition
shutdowner.hpp:214
so_5::extra::shutdowner::details::subscriber_info_t::m_sink
std::reference_wrapper< abstract_message_sink_t > m_sink
Actual subscriber.
Definition
shutdowner.hpp:199
so_5::extra::shutdowner::details::subscriber_info_t::subscriber_info_t
subscriber_info_t(abstract_message_sink_t &sink)
Message limit for that subscriber.
Definition
shutdowner.hpp:203
so_5::extra::shutdowner::shutdown_initiated_t
A message to be used to inform about start of shutdown operation.
Definition
shutdowner.hpp:52
Generated by
1.12.0