SObjectizer 5.8
Loading...
Searching...
No Matches
mchain_select.hpp
Go to the documentation of this file.
1/*
2 * SObjectizer-5
3 */
4
5/*!
6 * \file
7 * \brief Various stuff related to multi chain select.
8 *
9 * \since v.5.5.16
10 */
11
12#pragma once
13
14#include <so_5/mchain_select_ifaces.hpp>
15
16#include <so_5/details/at_scope_exit.hpp>
17#include <so_5/details/invoke_noexcept_code.hpp>
18#include <so_5/details/remaining_time_counter.hpp>
19#include <so_5/details/safe_cv_wait_for.hpp>
20
21#include <iterator>
22#include <array>
23
24#if defined(__clang__) && (__clang_major__ >= 16)
25#pragma clang diagnostic push
26#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
27#endif
28
29namespace so_5 {
30
31namespace mchain_props {
32
33namespace details {
34
35//
36// adv_select_data_t
37//
38//NOTE: there is no any additional data for select() function.
39using adv_select_data_t = bulk_processing_basic_data_t;
40
41} /* namespace details */
42
43} /* namespace mchain_props */
44
45//
46// mchain_select_result_t
47//
48/*!
49 * \brief A result of select from several mchains.
50 *
51 * \since v.5.7.0
52 */
54 {
55 //! Count of extracted incoming messages.
56 std::size_t m_extracted;
57 //! Count of handled incoming messages.
58 std::size_t m_handled;
59 //! Count of messages sent.
60 std::size_t m_sent;
61 //! Count of closed chains.
62 std::size_t m_closed;
63
64 public :
65 //! Default constructor.
67 : m_extracted{ 0u }
68 , m_handled{ 0u }
69 , m_sent{ 0u }
70 , m_closed{ 0u }
71 {}
72
73 //! Initializing constructor.
75 //! Count of extracted incoming messages.
76 std::size_t extracted,
77 //! Count of handled incoming messages.
78 std::size_t handled,
79 //! Count of messages sent.
80 std::size_t sent,
81 //! Count of closed chains.
82 std::size_t closed ) noexcept
83 : m_extracted{ extracted }
84 , m_handled{ handled }
85 , m_sent{ sent }
86 , m_closed{ closed }
87 {}
88
89 //! Count of extracted incoming messages.
90 [[nodiscard]]
91 std::size_t
92 extracted() const noexcept { return m_extracted; }
93
94 //! Count of handled incoming messages.
95 [[nodiscard]]
96 std::size_t
97 handled() const noexcept { return m_handled; }
98
99 //! Count of messages sent.
100 [[nodiscard]]
101 std::size_t
102 sent() const noexcept { return m_sent; }
103
104 //! Count of closed chains.
105 [[nodiscard]]
106 std::size_t
107 closed() const noexcept { return m_closed; }
108
109 /*!
110 * \return true if extracted() is not 0.
111 */
112 [[nodiscard]]
113 bool
114 was_extracted() const noexcept { return 0u != m_extracted; }
115
116 /*!
117 * \return true if handled() is not 0.
118 */
119 [[nodiscard]]
120 bool
121 was_handled() const noexcept { return 0u != m_handled; }
122
123 /*!
124 * \return true if sent() is not 0.
125 */
126 [[nodiscard]]
127 bool
128 was_sent() const noexcept { return 0u != m_sent; }
129
130 /*!
131 * \return true if closed() is not 0.
132 */
133 [[nodiscard]]
134 bool
135 was_closed() const noexcept { return 0u != m_closed; }
136
137 /*!
138 * \return true if something was sent or received/handled.
139 */
140 [[nodiscard]]
141 bool
142 was_sent_or_received() const noexcept
143 {
145 }
146 };
147
148//
149// mchain_select_params_t
150//
151/*!
152 * \brief Parameters for advanced select from multiple mchains.
153 *
154 * \sa so_5::select().
155 *
156 * \note Adds nothing to mchain_bulk_processing_params_t.
157 *
158 * \since v.5.5.16
159 */
160template< mchain_props::msg_count_status_t Msg_Count_Status >
161class mchain_select_params_t final
163 mchain_props::details::adv_select_data_t,
164 mchain_select_params_t< Msg_Count_Status > >
165 {
167 mchain_props::details::adv_select_data_t,
168 mchain_select_params_t< Msg_Count_Status > >;
169
170 public :
171 //! Make of clone with different Msg_Count_Status or return
172 //! a reference to the same object.
173 template< mchain_props::msg_count_status_t New_Msg_Count_Status >
174 [[nodiscard]]
175 decltype(auto)
177 {
178 if constexpr( New_Msg_Count_Status != Msg_Count_Status )
179 return mchain_select_params_t< New_Msg_Count_Status >{
180 this->so5_data()
181 };
182 else
183 return *this;
184 }
185
186 //! The default constructor.
188
189 //! Initializing constructor for the case of cloning.
191 typename base_type::data_type data )
192 : base_type{ std::move(data) }
193 {}
194 };
195
196//
197// from_all
198//
199/*!
200 * \brief Helper function for creation of mchain_select_params instance
201 * with default values.
202 *
203 * \attention
204 * Since v.5.6.0 at least handle_all(), handle_n() or extract_n() should be
205 * called before passing result of from_all() to select() or
206 * prepare_select() functions.
207 *
208 * Usage example:
209 * \code
210 select( so_5::from_all().handle_n(3).empty_timeout(3s), ... );
211 * \endcode
212 */
213inline mchain_select_params_t< mchain_props::msg_count_status_t::undefined >
215 {
216 return {};
217 }
218
219namespace mchain_props {
220
221namespace details {
222
223//
224// receive_select_case_t
225//
226/*!
227 * \brief A base class for implementations of select_case for the
228 * case of receiving messages.
229 *
230 * This class implements pure virtual try_handle() methods but introduces
231 * a new pure virtual method try_handle_extracted_message() that should
232 * be implemented in a derived class.
233 *
234 * \since v.5.7.0
235 */
237 {
238 public :
239 using select_case_t::select_case_t;
240
241 [[nodiscard]]
242 handling_result_t
243 try_handle( select_notificator_t & notificator ) override
244 {
245 // Please note that value of m_notificator will be
246 // returned to nullptr if a message extracted or
247 // channel is closed.
248 //
249 // NOTE: if extract() throws we don't know is the pointer
250 // to this select_case stored inside mchain or not.
251 // But is doesn't matter because in the case of an exception
252 // select operation will be aborted and on_select_finish()
253 // will be called for each select_case.
254 //
255 // But we don't reset m_notificator to nullptr in the case
256 // of an exception from extract(). It is for the case if
257 // mchain stores pointer to select_case and calls
258 // select_case's notify() method just before select operation
259 // is aborted (and on_select_finish() is called).
260 //
261 m_notificator = &notificator;
262
263 demand_t demand;
264 const auto status = extract( demand );
265 // Notificator pointer must retain its value only if
266 // there is no messages in mchain.
267 // In other cases this pointer must be dropped.
269 m_notificator = nullptr;
270
272 return try_handle_extracted_message( demand );
273
274 return mchain_receive_result_t{ 0u, 0u, status };
275 }
276
277 protected :
278 //! Attempt to handle extracted message.
279 /*!
280 * This method will be overriden in derived classes.
281 */
282 [[nodiscard]]
285 };
286
287//
288// send_select_case_t
289//
290/*!
291 * \brief A base class for implementations of select_case for the
292 * case of sending messages.
293 *
294 * This class implements pure virtual try_handle() methods but introduces
295 * a new pure virtual method on_successful_push() that should
296 * be implemented in a derived class.
297 *
298 * \since v.5.7.0
299 */
301 {
302 private :
303 //! Type of message to be sent.
304 std::type_index m_msg_type;
305 //! Message to be sent.
306 message_ref_t m_message;
307
308 public :
309 //! Initializing constructor.
311 mchain_t chain,
312 std::type_index msg_type,
313 message_ref_t message )
314 : select_case_t{ std::move(chain) }
315 , m_msg_type{ std::move(msg_type) }
316 , m_message{ std::move(message) }
317 {}
318
319 [[nodiscard]]
320 handling_result_t
321 try_handle( select_notificator_t & notificator ) override
322 {
323 // Please note that value of m_notificator will be
324 // returned to nullptr if a message stored into the mchain
325 // or channel is closed.
326 //
327 // NOTE: if push() throws we don't know is the pointer
328 // to this select_case stored inside mchain or not.
329 // But is doesn't matter because in the case of an exception
330 // select operation will be aborted and on_select_finish()
331 // will be called for each select_case.
332 //
333 // But we don't reset m_notificator to nullptr in the case
334 // of an exception from push(). It is for the case if
335 // mchain stores pointer to select_case and calls
336 // select_case's notify() method just before select operation
337 // is aborted (and on_select_finish() is called).
338 //
339 m_notificator = &notificator;
340
341 const auto status = push( m_msg_type, m_message );
342 // Notificator pointer must retain its value only if
343 // message is deffered.
344 // In other cases this pointer must be dropped.
345 if( push_status_t::deffered != status )
346 m_notificator = nullptr;
347
348 if( push_status_t::stored == status )
350
352 push_status_t::stored == status ? 1u : 0u,
353 status
354 };
355 }
356
357 protected :
358 //! Hook for handling successful push attempt.
359 /*!
360 * This method will be overriden in derived classes.
361 */
362 virtual void
364 };
365
366//
367// actual_receive_select_case_t
368//
369/*!
370 * \brief Actual implementation of one multi chain select case.
371 *
372 * \since v.5.5.16
373 */
374template< std::size_t N >
376 {
378
379 public :
380 //! Initializing constructor.
381 /*!
382 * \tparam Handlers list of message handlers for messages extracted
383 * from the mchain.
384 */
385 template< typename... Handlers >
387 //! Chain to be used for select.
388 mchain_t chain,
389 //! Message handlers.
390 Handlers &&... handlers )
392 {
395 0,
396 std::forward< Handlers >(handlers)... );
397 }
398
399 protected :
400 [[nodiscard]]
403 {
404 const bool handled = m_handlers.handle(
407
409 1u,
410 handled ? 1u : 0u,
412 }
413 };
414
415//
416// actual_send_select_case_t
417//
418/*!
419 * \brief The actual implementation of select_case for the case
420 * of sending a message.
421 *
422 * This implementation calls an instance of On_Success_Handler handler
423 * in on_successful_push() method.
424 *
425 * \tparam On_Success_Handler the type of handler to be called when
426 * the message is sent.
427 *
428 * \since v.5.7.0
429 */
430template< typename On_Success_Handler >
432 {
433 private :
434 //! Actual handler of successful send attempt.
435 On_Success_Handler m_success_handler;
436
437 public :
438 //! Initializing constructor for the case when success_handler is a const lvalue
440 mchain_t chain,
441 std::type_index msg_type,
442 message_ref_t message,
443 const On_Success_Handler & success_handler )
447 {}
448
449 //! Initializing constructor for the case when success_handler is a rvalue.
451 mchain_t chain,
452 std::type_index msg_type,
453 message_ref_t message,
454 On_Success_Handler && success_handler )
458 {}
459
460 protected :
461 void
463 {
465 }
466 };
467
468//
469// select_cases_holder_t
470//
471/*!
472 * \brief A holder for serie of select_cases.
473 *
474 * Provides access to select_cases via iterator and begin() and end() methods.
475 *
476 * \note This is moveable class, but not copyable.
477 *
478 * \since v.5.5.16
479 */
480template< std::size_t Cases_Count >
482 {
483 //! Type of array for holding select_cases.
484 using array_type_t = std::array< select_case_unique_ptr_t, Cases_Count >;
485 //! Storage for select_cases.
486 array_type_t m_cases;
487
488 public :
491 operator=( const select_cases_holder_t & ) = delete;
492
493 //! Default constructor.
496 //! Move constructor.
498 {
499 swap( *this, o );
500 }
501
502 //! Move operator.
505 {
507 swap( *this, tmp );
508
509 return *this;
510 }
511
512 //! Swap operation.
513 friend void
516 select_cases_holder_t & b ) noexcept
517 {
518 using std::swap;
519 for( std::size_t i = 0; i != Cases_Count; ++i )
520 swap( a.m_cases[ i ], b.m_cases[ i ] );
521 }
522
523 //! Helper method for setting up specific select_case.
524 /*!
525 * This method will be used during creation of select_cases_holder.
526 */
527 void
528 set_case( std::size_t index, select_case_unique_ptr_t c ) noexcept
529 {
530 m_cases[ index ] = std::move(c);
531 }
532
533 //! Get count of select_cases in holder.
534 [[nodiscard]]
535 std::size_t
536 size() const noexcept { return Cases_Count; }
537
538 //! Iterator class for accessing select_cases.
539 /*!
540 * Implements ForwardIterator concept.
541 */
543 {
544 using actual_it_t = typename array_type_t::const_iterator;
545
546 actual_it_t m_it;
547
548 public :
549 using difference_type = std::ptrdiff_t;
550 using value_type = select_case_t;
551 using pointer = const value_type*;
552 using reference = const value_type&;
553 using iterator_category = std::forward_iterator_tag;
554
555 const_iterator() = default;
556 const_iterator( actual_it_t it ) noexcept : m_it( std::move(it) ) {}
557
559 { ++m_it; return *this; }
560 const_iterator operator++(int) noexcept
561 { const_iterator o{ m_it }; ++m_it; return o; }
562
563 bool operator==( const const_iterator & o ) const noexcept
564 { return m_it == o.m_it; }
565 bool operator!=( const const_iterator & o ) const noexcept
566 { return m_it != o.m_it; }
567
568 select_case_t & operator*() const noexcept
569 { return **m_it; }
570 select_case_t * operator->() const noexcept
571 { return m_it->get(); }
572 };
573
574 //! Get iterator for the first item in select_cases_holder.
575 [[nodiscard]]
577 begin() const noexcept { return const_iterator{ m_cases.begin() }; }
578
579 //! Get iterator for the item just behind the last item in select_cases_holder.
580 [[nodiscard]]
582 end() const noexcept { return const_iterator{ m_cases.end() }; }
583 };
584
585//
586// fill_select_cases_holder
587//
588
589template< typename Holder >
590void
592 Holder & holder,
593 std::size_t index,
594 select_case_unique_ptr_t c )
595 {
597 }
598
599template< typename Holder, typename... Cases >
600void
602 Holder & holder,
603 std::size_t index,
604 select_case_unique_ptr_t c,
605 Cases &&... other_cases )
606 {
609 holder, index + 1, std::forward< Cases >(other_cases)... );
610 }
611
612/*!
613 * \brief The current status of prepared-select instance.
614 *
615 * If prepared-select instance is activated (is used in select() call)
616 * then this instance can't be activated yet more time.
617 *
618 * \since v.5.6.1
619 */
621 {
622 //! Prepared-select instance is not used in select() call.
623 passive,
624 //! Prepared-select instance is used in select() call now.
625 active
626 };
627
628/*!
629 * \brief A data for prepared-select instance.
630 *
631 * \note
632 * This data is protected by mutex. To get access to data it is
633 * necessary to use instances activation_locker_t class.
634 *
635 * \attention
636 * This class is not Moveable nor Copyable.
637 *
638 * \since v.5.6.1
639 */
640template< std::size_t Cases_Count >
642 {
643 //! The object's lock.
644 std::mutex m_lock;
645
646 //! The current status of extensible-select object.
649
650 //! Parameters for select.
651 const mchain_select_params_t<
653
654 //! A list of cases for extensible-select operation.
656
657 public :
659 const prepared_select_data_t & ) = delete;
661 prepared_select_data_t && ) = delete;
662
663 //! Initializing constructor.
664 template< typename... Cases >
666 mchain_select_params_t<
667 msg_count_status_t::defined > && params,
668 Cases && ...cases ) noexcept
669 : m_params{ std::move(params) }
670 {
671 static_assert( sizeof...(Cases) == Cases_Count,
672 "Cases_Count and sizeof...(Cases) mismatch" );
673
675 m_cases, 0u, std::forward<Cases>(cases)... );
676 }
677
678 friend class activation_locker_t;
679
680 /*!
681 * \brief Special class for locking prepared-select instance
682 * for activation inside select() call.
683 *
684 * This class acquires prepared-select instance's mutex for a
685 * short time twice:
686 *
687 * - the first time in the constructor to check the status of
688 * prepared-select instance and switch status to `active`;
689 * - the second time in the destructor to return status to
690 * `passive`.
691 *
692 * This logic allow an instance of activation_locker_t live for
693 * long time but not to block other instances of
694 * activation_locker_t.
695 *
696 * \attention
697 * The constructor of activation_locker_t throws if prepared-select
698 * instance is used in select() call.
699 *
700 * \note
701 * This class is not Moveable nor Copyable.
702 *
703 * \since v.5.6.1
704 */
706 {
708
709 public :
711 const activation_locker_t & ) = delete;
713 activation_locker_t && ) = delete;
714
715 activation_locker_t(
717 : m_data{ data }
718 {
719 // Lock the data object only for changing the status.
721
725 "an activate prepared-select "
726 "that is already active" );
727
729 }
730
731 ~activation_locker_t() noexcept
732 {
733 // Lock the data object only for changing the status.
735
737 }
738
739 const auto &
740 params() const noexcept
741 {
742 return m_data.get().m_params;
743 }
744
745 const auto &
746 cases() const noexcept
747 {
748 return m_data.get().m_cases;
749 }
750 };
751 };
752
753//
754// extensible_select_cases_holder_t
755//
756/*!
757 * \brief A holder for serie of select_cases for the case of extensible select.
758 *
759 * Provides access to select_cases via iterator and begin() and end() methods.
760 *
761 * \note This is moveable class, but not copyable.
762 *
763 * \since v.5.6.1
764 */
766 {
767 //! Type of array for holding select_cases.
768 using array_type_t = std::vector< select_case_unique_ptr_t >;
769 //! Storage for select_cases.
770 array_type_t m_cases;
771
772 public :
774 const extensible_select_cases_holder_t & ) = delete;
777 const extensible_select_cases_holder_t & ) = delete;
778
779 //! Swap operation.
780 friend void
784 {
785 using std::swap;
786 swap( a.m_cases, b.m_cases );
787 }
788
789 //! Default constructor.
792 //! Constructor with initial capacity.
794 std::size_t initial_capacity )
795 {
796 if( 0u != initial_capacity )
797 m_cases.reserve( initial_capacity );
798 }
799 //! Move constructor.
804
805 //! Move operator.
808 {
809 extensible_select_cases_holder_t tmp( std::move( o ) );
810 swap( *this, tmp );
811
812 return *this;
813 }
814
815 //! Helper method for setting up specific select_case.
816 /*!
817 * This method will be used during creation of select_cases_holder.
818 */
819 void
820 add_case( select_case_unique_ptr_t c )
821 {
822 m_cases.push_back( std::move(c) );
823 }
824
825 //! Get count of select_cases in holder.
826 std::size_t
827 size() const noexcept { return m_cases.size(); }
828
829 //! Iterator class for accessing select_cases.
830 /*!
831 * Implements ForwardIterator concept.
832 */
834 {
835 using actual_it_t = typename array_type_t::const_iterator;
836
837 actual_it_t m_it;
838
839 public :
840 using difference_type = std::ptrdiff_t;
841 using value_type = select_case_t;
842 using pointer = const value_type*;
843 using reference = const value_type&;
844 using iterator_category = std::forward_iterator_tag;
845
846 const_iterator() = default;
847 const_iterator( actual_it_t it ) noexcept : m_it( std::move(it) ) {}
848
850 { ++m_it; return *this; }
851 const_iterator operator++(int) noexcept
852 { const_iterator o{ m_it }; ++m_it; return o; }
853
854 bool operator==( const const_iterator & o ) const noexcept
855 { return m_it == o.m_it; }
856 bool operator!=( const const_iterator & o ) const noexcept
857 { return m_it != o.m_it; }
858
859 select_case_t & operator*() const noexcept
860 { return **m_it; }
861 select_case_t * operator->() const noexcept
862 { return m_it->get(); }
863 };
864
865 //! Get iterator for the first item in select_cases_holder.
867 begin() const noexcept { return const_iterator{ m_cases.begin() }; }
868
869 //! Get iterator for the item just behind the last item in select_cases_holder.
871 end() const noexcept { return const_iterator{ m_cases.end() }; }
872 };
873
874inline void
878
879template< typename... Cases >
880void
883 select_case_unique_ptr_t c,
884 Cases &&... other_cases )
885 {
886 holder.add_case( std::move(c) );
887 if constexpr( 0u != sizeof...(other_cases) )
889 holder,
891 }
892
893/*!
894 * \brief The current status of extensible-select instance.
895 *
896 * If extensible-select instance is activated (is used in select() call)
897 * then this instance can't be modified or activated yet more time.
898 *
899 * \since v.5.6.1
900 */
902 {
903 //! Extensible-select instance is not used in select() call.
904 passive,
905 //! Extensible-select instance is used in select() call now.
906 active
907 };
908
909/*!
910 * \brief A data for extensible-select instance.
911 *
912 * \note
913 * This data is protected by mutex. To get access to data it is
914 * necessary to use instances of modification_locker_t and
915 * activation_locker_t classes.
916 *
917 * \attention
918 * This class is not Moveable nor Copyable.
919 *
920 * \since v.5.6.1
921 */
923 {
924 //! The object's lock.
925 std::mutex m_lock;
926
927 //! The current status of extensible-select object.
930
931 //! Parameters for select.
932 const mchain_select_params_t<
934
935 //! A list of cases for extensible-select operation.
937
938 public :
940 const extensible_select_data_t & ) = delete;
942 extensible_select_data_t && ) = delete;
943
944 //! Initializing constructor.
946 mchain_select_params_t<
947 msg_count_status_t::defined > && params,
948 extensible_select_cases_holder_t && cases ) noexcept
949 : m_params{ std::move(params) }
950 , m_cases{ std::move(cases) }
951 {}
952
953 friend class modification_locker_t;
954
955 /*!
956 * \brief Special class for locking extensible-select instance
957 * for modification.
958 *
959 * Acquires extensible-select instance's in the constructor and
960 * releases in the destructor.
961 *
962 * It is possible to have several modification_locker_t instances
963 * for one extensible-select instance in different threads at
964 * the same time. All of them except one will be blocked on
965 * extensible-select instance's mutex.
966 *
967 * \attention
968 * The constructor of modification_locker_t throws if extensible-select
969 * instance is used in select() call.
970 *
971 * \note
972 * This class is not Moveable nor Copyable.
973 *
974 * \since v.5.6.1
975 */
977 {
979 std::lock_guard< std::mutex > m_lock;
980
981 public :
983 const modification_locker_t & ) = delete;
985 modification_locker_t && ) = delete;
986
987 modification_locker_t(
989 : m_data{ data }
991 {
995 "an attempt to modify extensible-select "
996 "that is already active" );
997 }
998
999 //! Get access to cases-holder for modification.
1000 auto &
1001 cases() const noexcept
1002 {
1003 return m_data.get().m_cases;
1004 }
1005 };
1006
1007 friend class activation_locker_t;
1008
1009 /*!
1010 * \brief Special class for locking extensible-select instance
1011 * for activation inside select() call.
1012 *
1013 * This class acquires extensible-select instance's mutex for a
1014 * short time twice:
1015 *
1016 * - the first time in the constructor to check the status of
1017 * extensible-select instance and switch status to `active`;
1018 * - the second time in the destructor to return status to
1019 * `passive`.
1020 *
1021 * This logic allow an instance of activation_locker_t live for
1022 * long time but not to block other instances of
1023 * modification_locker_t or activation_locker_t.
1024 *
1025 * \attention
1026 * The constructor of activation_locker_t throws if extensible-select
1027 * instance is used in select() call.
1028 *
1029 * \note
1030 * This class is not Moveable nor Copyable.
1031 *
1032 * \since v.5.6.1
1033 */
1035 {
1037
1038 public :
1040 const activation_locker_t & ) = delete;
1042 activation_locker_t && ) = delete;
1043
1044 activation_locker_t(
1046 : m_data{ data }
1047 {
1048 // Lock the data object only for changing the status.
1049 std::lock_guard< std::mutex > lock{ m_data.get().m_lock };
1050
1054 "an activate extensible-select "
1055 "that is already active" );
1056
1058 }
1059
1060 ~activation_locker_t() noexcept
1061 {
1062 // Lock the data object only for changing the status.
1063 std::lock_guard< std::mutex > lock{ m_data.get().m_lock };
1064
1066 }
1067
1068 const auto &
1069 params() const noexcept
1070 {
1071 return m_data.get().m_params;
1072 }
1073
1074 const auto &
1075 cases() const noexcept
1076 {
1077 return m_data.get().m_cases;
1078 }
1079 };
1080 };
1081
1082#if defined(__clang__)
1083#pragma clang diagnostic push
1084#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
1085#endif
1086
1087//
1088// actual_select_notificator_t
1089//
1090/*!
1091 * \brief Actual implementation of notificator for multi chain select.
1092 *
1093 * \since v.5.5.16
1094 */
1096 {
1097 private :
1098 std::mutex m_lock;
1099 std::condition_variable m_condition;
1100
1101 //! Queue of already notified select_cases.
1103
1104 /*!
1105 * \attention This method must be called only on locked object.
1106 */
1107 void
1109 {
1110 what.set_next( m_tail );
1111 m_tail = &what;
1112 }
1113
1114 public :
1115 /*!
1116 * \brief Initializing constructor.
1117 *
1118 * Intended to be used with select_cases_holder and its iterators.
1119 *
1120 * Every select_case is automatically added to the list of notified
1121 * select_cases.
1122 */
1123 template< typename Fwd_it >
1124 actual_select_notificator_t( Fwd_it b, Fwd_it e )
1125 {
1126 // All select_cases from range [b,e) must be included in
1127 // ready_cases list.
1128 while( b != e )
1129 {
1130 b->set_next( m_tail );
1131 m_tail = &(*b);
1132 ++b;
1133 }
1134 }
1135
1136 void
1137 notify( select_case_t & what ) noexcept override
1138 {
1139 select_case_t * old_tail = nullptr;
1140 {
1141 std::lock_guard< std::mutex > lock{ m_lock };
1142
1143 old_tail = m_tail;
1145 }
1146
1147 if( !old_tail )
1148 m_condition.notify_one();
1149 }
1150
1151 /*!
1152 * \brief Return specifed select_case object to the chain of
1153 * 'notified select_cases'.
1154 *
1155 * If a message has been read from a mchain then there could be
1156 * other messages in that mchain. Because of that the select_case
1157 * for that mchain must be seen as 'notified' -- it should be
1158 * processed on next call to wait() method. This method must be
1159 * used for immediately return of select_case to the chain of
1160 * 'notified select_cases'.
1161 */
1162 void
1164 {
1165 std::lock_guard< std::mutex > lock{ m_lock };
1167 }
1168
1169 /*!
1170 * \brief Wait for any notified select_case.
1171 *
1172 * Waiting no more than \a wait_time.
1173 *
1174 * \return nullptr if there is no notified select_cases after
1175 * waiting for \a wait_time.
1176 */
1177 [[nodiscard]]
1180 //! Maximum waiting time for notified select_case.
1181 duration_t wait_time )
1182 {
1183 std::unique_lock< std::mutex > lock{ m_lock };
1184 if( !m_tail )
1186 lock,
1188 wait_time,
1189 [this]{ return m_tail != nullptr; } );
1190
1191 auto * result = m_tail;
1192 m_tail = nullptr;
1193
1194 return result;
1195 }
1196 };
1197
1198#if defined(__clang__)
1199#pragma clang diagnostic pop
1200#endif
1201
1202//
1203// select_actions_performer_t
1204//
1205/*!
1206 * \brief Helper class for performing select-specific operations.
1207 *
1208 * \tparam Holder type of actual select_cases_holder_t.
1209 *
1210 * \since v.5.5.16
1211 */
1212template< typename Holder >
1214 {
1215 const mchain_select_params_t< msg_count_status_t::defined > & m_params;
1216
1217 const Holder & m_select_cases;
1219
1220 std::size_t m_closed_chains = 0;
1221 std::size_t m_extracted_messages = 0;
1222 std::size_t m_handled_messages = 0;
1223 std::size_t m_sent_messages = 0;
1224
1225 /*!
1226 * \brief The counter of completed send_cases.
1227 *
1228 * A send_case is completed if the corresponding message is sent
1229 * of if the target mchain is closed.
1230 *
1231 * \since v.5.7.0
1232 */
1233 std::size_t m_completed_send_cases = 0;
1234
1237
1238 bool m_can_continue = true;
1239
1240 public :
1242 const mchain_select_params_t< msg_count_status_t::defined > & params,
1243 const Holder & select_cases )
1244 : m_params( params )
1245 , m_select_cases( select_cases )
1246 , m_notificator( select_cases.begin(), select_cases.end() )
1247 {}
1249 {
1250 for( auto & c : m_select_cases )
1251 c.on_select_finish();
1252 }
1253
1254 void
1255 handle_next( const duration_t & wait_time )
1256 {
1257 select_case_t * ready_chain = m_notificator.wait( wait_time );
1258 if( !ready_chain )
1259 {
1262 }
1263 else
1264 handle_ready_chain( ready_chain );
1265 }
1266
1269
1270 bool
1271 can_continue() const noexcept { return m_can_continue; }
1272
1274 make_result() const noexcept
1275 {
1276 return {
1281 };
1282 }
1283
1284 private :
1285 friend struct select_result_handler_t;
1286 struct select_result_handler_t final
1287 {
1290
1291 void operator()( const mchain_receive_result_t & result ) const {
1292 m_performer->on_receive_result( m_current, result );
1293 }
1294
1295 void operator()( const mchain_send_result_t & result ) const {
1296 m_performer->on_send_result( m_current, result );
1297 }
1298 };
1299
1300 void
1302 {
1303 while( ready_chain && m_can_continue )
1304 {
1305 auto * current = ready_chain;
1306 ready_chain = current->giveout_next();
1307
1308 std::visit(
1309 select_result_handler_t{ this, current },
1310 current->try_handle( m_notificator ) );
1311
1313 }
1314 }
1315
1316 void
1318 select_case_t * current,
1319 const mchain_receive_result_t & result )
1320 {
1322
1324 {
1327
1328 // The mchain from 'current' can contain more
1329 // messages. We should return this case to 'ready_chain'
1330 // of the notificator.
1332 }
1334 {
1335 react_on_closed_chain( current );
1336 }
1337 }
1338
1339 void
1341 select_case_t * current,
1342 const mchain_send_result_t & result )
1343 {
1344 // No extracted messages for that case.
1346
1347 switch( result.status() )
1348 {
1351 m_sent_messages += result.sent();
1352 break;
1353
1355 // Nothing to do. Another attempt could be performed later.
1356 break;
1357
1359 // Message wasn't sent but the send_case completed.
1361 break;
1362
1364 // Message wasn't sent but the send_case completed.
1366 react_on_closed_chain( current );
1367 break;
1368 }
1369 }
1370
1371 void
1373 {
1375
1376 // Since v.5.5.17 chain_closed handler must be
1377 // used on chain_closed event.
1378 if( const auto & handler = m_params.closed_handler() )
1379 so_5::details::invoke_noexcept_code(
1380 [&handler, current] {
1381 handler( current->chain() );
1382 } );
1383 }
1384
1385 void
1387 {
1388 auto fn = [this] {
1389 if( m_closed_chains == m_select_cases.size() )
1390 return false;
1391
1393 return false;
1394
1398 return false;
1399
1402 return false;
1403
1405 return false;
1406
1407 return true;
1408 };
1409
1410 m_can_continue = fn();
1411 }
1412 };
1413
1414template< typename Holder >
1417 const mchain_select_params_t< msg_count_status_t::defined > & params,
1418 const Holder & select_cases )
1419 {
1420 using namespace so_5::details;
1421
1422 select_actions_performer_t< Holder > performer{ params, select_cases };
1423
1424 remaining_time_counter_t total_time_counter{ params.total_time() };
1425 remaining_time_counter_t wait_incoming_time{ params.empty_timeout() };
1426 do
1427 {
1428 // Since v.5.8.4 we have to take the empty_timeout value
1429 // into the account.
1430 const duration_t this_iteration_wait_time = std::min(
1431 total_time_counter.remaining(),
1432 wait_incoming_time.remaining() );
1433
1434 performer.handle_next( this_iteration_wait_time );
1436 performer.last_extraction_status() )
1437 // Becase some message extracted we must restart
1438 // wait_incoming_time counting.
1439 wait_incoming_time =
1441 else
1442 // Otherwise wait_incoming_time should be updated to
1443 // reduce it value.
1444 wait_incoming_time.update();
1445
1446 total_time_counter.update();
1447 }
1448 while( total_time_counter
1449 && wait_incoming_time
1450 && performer.can_continue() );
1451
1452 return performer.make_result();
1453 }
1454
1455template< typename Holder >
1458 const mchain_select_params_t< msg_count_status_t::defined > & params,
1459 const Holder & select_cases )
1460 {
1461 using namespace so_5::details;
1462
1463 select_actions_performer_t< Holder > performer{ params, select_cases };
1464
1466 do
1467 {
1468 performer.handle_next( wait_time.remaining() );
1470 performer.last_extraction_status() )
1471 // Becase some message extracted we must restart wait_time
1472 // counting.
1474 else
1475 // There could be one of two situations:
1476 // 1) several threads do select on the same mchain.
1477 // Both threads will be awoken when some message is
1478 // pushed into the mchain. But only one thread will get
1479 // this message. Second thread will receive no_messages
1480 // status. In this case we should wait for the next message,
1481 // but wait_time must be decremented.
1482 // 2) some chain is closed. Wait time should be updated and
1483 // next wait attempt must be performed.
1484 wait_time.update();
1485 }
1486 while( wait_time && performer.can_continue() );
1487
1488 return performer.make_result();
1489 }
1490
1491//
1492// perform_select
1493//
1494/*!
1495 * \brief Helper function with implementation of main select action.
1496 *
1497 * \since v.5.5.17
1498 */
1499template< typename Cases_Holder >
1502 //! Parameters for advanced select.
1503 const mchain_select_params_t< msg_count_status_t::defined > & params,
1504 //! Select cases.
1505 const Cases_Holder & cases_holder )
1506 {
1508 return do_adv_select_without_total_time( params, cases_holder );
1509 else
1510 return do_adv_select_with_total_time( params, cases_holder );
1511 }
1512
1513} /* namespace details */
1514
1515} /* namespace mchain_props */
1516
1517//
1518// receive_case
1519//
1520/*!
1521 * \brief A helper for creation of select_case object for one multi chain
1522 * select.
1523 *
1524 * \attention It is an error if there are more than one handler for the
1525 * same message type in \a handlers.
1526 *
1527 * \sa so_5::select()
1528 *
1529 * \since v.5.5.16
1530 */
1531template< typename... Handlers >
1532[[nodiscard]]
1533mchain_props::select_case_unique_ptr_t
1535 //! Message chain to be used in select.
1536 mchain_t chain,
1537 //! Message handlers for messages extracted from that chain.
1538 Handlers &&... handlers )
1539 {
1540 using namespace mchain_props;
1541 using namespace mchain_props::details;
1542
1544 new actual_receive_select_case_t< sizeof...(handlers) >{
1545 std::move(chain),
1546 std::forward< Handlers >(handlers)... } };
1547 }
1548
1549//
1550// send_case
1551//
1552/*!
1553 * \brief A helper for creation of select_case object for one send-case
1554 * of a multi chain select.
1555 *
1556 * \sa so_5::select()
1557 *
1558 * \since v.5.7.0
1559 */
1560template<
1561 typename Msg,
1562 message_ownership_t Ownership,
1563 typename On_Success_Handler >
1564[[nodiscard]]
1565mchain_props::select_case_unique_ptr_t
1567 //! Message chain to be used in select.
1568 mchain_t chain,
1569 //! Message instance to be sent.
1570 message_holder_t< Msg, Ownership > msg,
1571 On_Success_Handler && handler )
1572 {
1573 using namespace mchain_props;
1574 using namespace mchain_props::details;
1575
1578
1580 new select_case_type{
1581 std::move(chain),
1585 }
1586 };
1587 }
1588
1589/*!
1590 * \brief An advanced form of multi chain select.
1591 *
1592 * \attention The behaviour is not defined if a mchain is used in different
1593 * select_cases.
1594 *
1595 * \attention
1596 * Since v.5.6.0 at least handle_all(), handle_n() or extract_n() should be
1597 * called before passing result of from_all() to select() function.
1598 *
1599 * \par Usage examples:
1600 \code
1601 using namespace so_5;
1602
1603 mchain_t ch1 = env.create_mchain(...);
1604 mchain_t ch2 = env.create_mchain(...);
1605
1606 // Receive and handle 3 messages.
1607 // It could be 3 messages from ch1. Or 2 messages from ch1 and 1 message
1608 // from ch2. Or 1 message from ch1 and 2 messages from ch2. And so on...
1609 //
1610 // If there is no 3 messages in mchains the select will wait infinitely.
1611 // A return from select will be after handling of 3 messages or
1612 // if all mchains are closed explicitely.
1613 select( from_all().handle_n( 3 ),
1614 receive_case( ch1,
1615 []( const first_message_type & msg ) { ... },
1616 []( const second_message_type & msg ) { ... } ),
1617 receive_case( ch2,
1618 []( const third_message_type & msg ) { ... },
1619 handler< some_signal_type >( []{ ... ] ),
1620 ... ) );
1621
1622 // Receive and handle 3 messages.
1623 // If there is no 3 messages in chains the select will wait
1624 // no more that 200ms.
1625 // A return from select will be after handling of 3 messages or
1626 // if all mchains are closed explicitely, or if there is no messages
1627 // for more than 200ms.
1628 select( from_all().handle_n( 3 ).empty_timeout( milliseconds(200) ),
1629 receive_case( ch1,
1630 []( const first_message_type & msg ) { ... },
1631 []( const second_message_type & msg ) { ... } ),
1632 receive_case( ch2,
1633 []( const third_message_type & msg ) { ... },
1634 handler< some_signal_type >( []{ ... ] ),
1635 ... ) );
1636
1637 // Receive all messages from mchains.
1638 // If there is no message in any of mchains then wait no more than 500ms.
1639 // A return from select will be after explicit close of all mchains
1640 // or if there is no messages for more than 500ms.
1641 select( from_all().handle_all().empty_timeout( milliseconds(500) ),
1642 receive_case( ch1,
1643 []( const first_message_type & msg ) { ... },
1644 []( const second_message_type & msg ) { ... } ),
1645 receive_case( ch2,
1646 []( const third_message_type & msg ) { ... },
1647 handler< some_signal_type >( []{ ... ] ),
1648 ... ) );
1649
1650 // Receve any number of messages from mchains but do waiting and
1651 // handling for no more than 2s.
1652 select( from_all().handle_all().total_time( seconds(2) ),
1653 receive_case( ch1,
1654 []( const first_message_type & msg ) { ... },
1655 []( const second_message_type & msg ) { ... } ),
1656 receive_case( ch2,
1657 []( const third_message_type & msg ) { ... },
1658 handler< some_signal_type >( []{ ... ] ),
1659 ... ) );
1660
1661 // Receve 1000 messages from chains but do waiting and
1662 // handling for no more than 2s.
1663 select( from_all().extract_n( 1000 ).total_time( seconds(2) ),
1664 receive_case( ch1,
1665 []( const first_message_type & msg ) { ... },
1666 []( const second_message_type & msg ) { ... } ),
1667 receive_case( ch2,
1668 []( const third_message_type & msg ) { ... },
1669 handler< some_signal_type >( []{ ... ] ),
1670 ... ) );
1671 \endcode
1672 *
1673 * \note
1674 * Since v.5.8.4 the value of empty_timeout (or no_wait_on_empty) is
1675 * taken into account when `total_time` is specified. It means that
1676 * in the following example the select() returns immediately if
1677 * all mchains are empty:
1678 * \code
1679 * select(
1680 * from_all().handle_n(5).no_wait_on_empty().total_time(6s),
1681 * receive_case( ch1, ...),
1682 * receive_case( ch2, ...) );
1683 * \endcode
1684 *
1685 * \since v.5.5.16
1686 */
1687template<
1688 mchain_props::msg_count_status_t Msg_Count_Status,
1689 typename... Cases >
1692 //! Parameters for advanced select.
1693 const mchain_select_params_t< Msg_Count_Status > & params,
1694 //! Select cases.
1695 Cases &&... cases )
1696 {
1697 static_assert(
1699 "message count to be processed/extracted should be defined "
1700 "by using handle_all()/handle_n()/extract_n() methods" );
1701
1702 using namespace mchain_props;
1703 using namespace mchain_props::details;
1704
1707 cases_holder, 0, std::forward< Cases >(cases)... );
1708
1710 }
1711
1712//
1713// prepared_select_t
1714//
1715/*!
1716 * \brief Special container for holding select parameters and select cases.
1717 *
1718 * \note Instances of that type usually used without specifying the actual
1719 * type:
1720 * \code
1721 auto prepared = so_5::prepare_select(
1722 so_5::from_all().handle_n(10).empty_timeout(10s),
1723 receive_case( ch1, some_handlers... ),
1724 receive_case( ch2, more_handlers... ), ... );
1725 ...
1726 auto r = so_5::select( prepared );
1727 * \endcode
1728 *
1729 * \note
1730 * This is a moveable type, not copyable. It is very like to unique_ptr.
1731 * Because of that an instance of prepared_select_t can empty. It means
1732 * that the actual content (e.g. prepared-select object) was moved to
1733 * another prepared_select_t instance. Usage of empty prepared_select_t
1734 * is an error and can lead to null-pointer dereference. SObjectizer doesn't
1735 * check the emptiness of prepared_select_t object.
1736 *
1737 * \since v.5.5.17
1738 */
1739template< std::size_t Cases_Count >
1741 {
1742 template<
1743 mchain_props::msg_count_status_t Msg_Count_Status,
1744 typename... Cases >
1745 friend prepared_select_t< sizeof...(Cases) >
1747 mchain_select_params_t< Msg_Count_Status > params,
1748 Cases &&... cases );
1749
1750 //! The actual prepared-select object.
1751 /*!
1752 * \note
1753 * Can be null if the actual content was moved to another
1754 * prepared_select_t instance.
1755 *
1756 * \since v.5.6.1
1757 */
1758 std::unique_ptr<
1761
1762 //! Initializing constructor.
1763 /*!
1764 * \note
1765 * This constructor is private since v.5.6.1
1766 */
1767 template< typename... Cases >
1769 mchain_select_params_t<
1771 Cases &&... cases )
1772 : m_data{
1775 std::move(params),
1776 std::forward<Cases>(cases)... ) }
1777 {}
1778
1779 public :
1782 operator=( const prepared_select_t & ) = delete;
1783
1784 //! Move constructor.
1786 prepared_select_t && other ) noexcept
1787 : m_data( std::move(other.m_data) )
1788 {}
1789
1790 //! Move operator.
1792 operator=( prepared_select_t && other ) noexcept
1793 {
1795 swap( *this, tmp);
1796 return *this;
1797 }
1798
1799 //! Swap operation.
1800 friend void
1802 {
1803 using std::swap;
1804 swap( a.m_data, b.m_data );
1805 }
1806
1807 //! Is this handle empty?
1808 /*!
1809 * \since v.5.6.1
1810 */
1811 bool
1812 empty() const noexcept { return !m_data; }
1813
1814 /*!
1815 * \name Getters
1816 * \{
1817 */
1818 auto &
1819 data() const noexcept { return *m_data; }
1820 /*!
1821 * \}
1822 */
1823 };
1824
1825//
1826// prepare_select
1827//
1828/*!
1829 * \brief Create prepared select statement to be used later.
1830 *
1831 * \attention
1832 * Since v.5.6.0 at least handle_all(), handle_n() or extract_n() should be
1833 * called before passing result of from_all() to prepare_select() function.
1834 *
1835 * Accepts all parameters as advanced select() version. For example:
1836 * \code
1837 // Receive and handle 3 messages.
1838 // If there is no 3 messages in chains the select will wait
1839 // no more that 200ms.
1840 // A return from select will be after handling of 3 messages or
1841 // if all mchains are closed explicitely, or if there is no messages
1842 // for more than 200ms.
1843 auto prepared1 = prepare_select(
1844 so_5::from_all().handle_n( 3 ).empty_timeout( milliseconds(200) ),
1845 receive_case( ch1,
1846 []( const first_message_type & msg ) { ... },
1847 []( const second_message_type & msg ) { ... } ),
1848 receive_case( ch2,
1849 []( const third_message_type & msg ) { ... },
1850 handler< some_signal_type >( []{ ... ] ),
1851 ... ) );
1852
1853 // Receive all messages from mchains.
1854 // If there is no message in any of mchains then wait no more than 500ms.
1855 // A return from select will be after explicit close of all mchains
1856 // or if there is no messages for more than 500ms.
1857 auto prepared2 = prepare_select(
1858 so_5::from_all().handle_all().empty_timeout( milliseconds(500) ),
1859 receive_case( ch1,
1860 []( const first_message_type & msg ) { ... },
1861 []( const second_message_type & msg ) { ... } ),
1862 receive_case( ch2,
1863 []( const third_message_type & msg ) { ... },
1864 handler< some_signal_type >( []{ ... ] ),
1865 ... ) );
1866 * \endcode
1867 *
1868 * \note
1869 * Since v.5.8.4 the value of empty_timeout (or no_wait_on_empty) is
1870 * taken into account when `total_time` is specified. It means that
1871 * in the following example the select() returns immediately if
1872 * all mchains are empty:
1873 * \code
1874 * auto prepared = prepare_select(
1875 * from_all().handle_n(5).no_wait_on_empty().total_time(6s),
1876 * receive_case( ch1, ...),
1877 * receive_case( ch2, ...) );
1878 * ...
1879 * so_5::select(prepared);
1880 * \endcode
1881 *
1882 * \since v.5.5.17
1883 */
1884template<
1885 mchain_props::msg_count_status_t Msg_Count_Status,
1886 typename... Cases >
1887prepared_select_t< sizeof...(Cases) >
1889 //! Parameters for advanced select.
1890 mchain_select_params_t< Msg_Count_Status > params,
1891 //! Select cases.
1892 Cases &&... cases )
1893 {
1894 static_assert(
1896 "message count to be processed/extracted should be defined "
1897 "by using handle_all()/handle_n()/extract_n() methods" );
1898
1899 return prepared_select_t< sizeof...(Cases) >(
1900 std::move(params),
1901 std::forward<Cases>(cases)... );
1902 }
1903
1904/*!
1905 * \brief A select operation to be done on previously prepared select params.
1906 *
1907 * Usage of ordinary forms of select() functions inside loops could be
1908 * inefficient because of wasting resources on constructions of internal
1909 * objects with descriptions of select cases on each select() call. More
1910 * efficient way is preparation of all select params and reusing them later. A
1911 * combination of so_5::prepare_select() and so_5::select(prepared_select_t)
1912 * allows to do that.
1913 *
1914 * Usage example:
1915 * \code
1916 auto prepared = so_5::prepare_select(
1917 so_5::from_all().extract_n(10).empty_timeout(200ms),
1918 receive_case( ch1, some_handlers... ),
1919 receive_case( ch2, more_handlers... ),
1920 receive_case( ch3, yet_more_handlers... ) );
1921 ...
1922 while( !some_condition )
1923 {
1924 auto r = so_5::select( prepared );
1925 ...
1926 }
1927 * \endcode
1928 *
1929 * \attention
1930 * Since v.5.6.1 there is a check for usage of prepared-select object
1931 * in parallel/nested calls to select(). If such call detected then
1932 * an exception is thrown.
1933 *
1934 * \since v.5.5.17
1935 */
1936template< std::size_t Cases_Count >
1939 const prepared_select_t< Cases_Count > & prepared )
1940 {
1941 using namespace mchain_props::details;
1942
1945 };
1946
1948 locker.params(),
1949 locker.cases() );
1950 }
1951
1952//
1953// extensible_select_t
1954//
1955/*!
1956 * \brief Special container for holding select parameters and select cases.
1957 *
1958 * This type is a *handle* for extensible-select instance. It's like
1959 * unique_ptr. Just one instance of extensible_select_t owns the instance
1960 * of extensible-select.
1961 *
1962 * \attention
1963 * Because extensible_select_t is like to unique_ptr it can be in an empty
1964 * state (it means that there is no actual extensible-select instance behind
1965 * the handle). Usage of empty extensible_select_t object in call to
1966 * select() is an error. SObjectizer doesn't check the emptiness of
1967 * extensible_select_t object. An attempt to pass an empty extensible_select_t
1968 * to select() will lead to null-pointer dereference.
1969 *
1970 * \note
1971 * This is Moveable type but not Copyable.
1972 *
1973 * \since v.5.6.1
1974 */
1976 {
1977 template<
1978 mchain_props::msg_count_status_t Msg_Count_Status,
1979 typename... Cases >
1980 friend extensible_select_t
1982 mchain_select_params_t< Msg_Count_Status > params,
1983 Cases &&... cases );
1984
1985 //! Actual data for that extensible-select.
1987
1988 //! Actual initializing constructor.
1990 std::unique_ptr< mchain_props::details::extensible_select_data_t > data )
1991 : m_data{ std::move(data) }
1992 {}
1993
1994 public :
1997 operator=( const extensible_select_t & ) = delete;
1998
1999 //! Default constructor.
2000 /*!
2001 * \attention
2002 * This constructor is intended for the cases like that:
2003 * \code
2004 * class some_my_data {
2005 * so_5::extensible_select_t m_select_handle;
2006 * ...
2007 * void on_some_stage() {
2008 * m_select_handle = so_5::make_extensible_select(...);
2009 * ...
2010 * }
2011 * void on_another_stage() {
2012 * so_5::add_select_cases(m_select_handle, ...);
2013 * ...
2014 * }
2015 * void on_yet_another_stage() {
2016 * auto r = so_5::select(m_select_handle);
2017 * ...
2018 * }
2019 * ...
2020 * };
2021 * \endcode
2022 */
2024
2025 //! Move constructor.
2027 extensible_select_t && other ) noexcept
2028 : m_data{ std::move(other.m_data) }
2029 {}
2030
2031 //! Move operator.
2033 operator=( extensible_select_t && other ) noexcept
2034 {
2035 extensible_select_t tmp( std::move(other) );
2036 swap( *this, tmp);
2037 return *this;
2038 }
2039
2040 //! Swap operation.
2041 friend void
2043 {
2044 using std::swap;
2045 swap( a.m_data, b.m_data );
2046 }
2047
2048 //! Is this handle empty?
2049 bool
2050 empty() const noexcept { return !m_data; }
2051
2052 /*!
2053 * \name Getters
2054 * \{
2055 */
2056 auto &
2057 data() const noexcept { return *m_data; }
2058 /*!
2059 * \}
2060 */
2061 };
2062
2063/*!
2064 * \brief Creation of extensible-select instance.
2065 *
2066 * This function creates an instance of extensible-select object that
2067 * can be used for subsequent calls to add_select_cases() and
2068 * select().
2069 *
2070 * Usage examples:
2071 * \code
2072 * // Creation of extensible-select instance with initial set of cases.
2073 * auto sel = so_5::make_extensible_select(
2074 * so_5::from_all().handle_n(10),
2075 * receive_case(ch1, ...),
2076 * receive_case(ch2, ...));
2077 *
2078 * // Creation of extensible-select instance without initial set of cases.
2079 * auto sel2 = so_5::make_extensible_select(
2080 * so_5::from_all().handle_n(20));
2081 * // Cases should be added later.
2082 * so_5::add_select_cases(sel2, receive_case(ch1, ...));
2083 * so_5::add_select_cases(sel2,
2084 * receive_case(ch2, ...),
2085 * receive_case(ch3, ...));
2086 * \endcode
2087 *
2088 * \note
2089 * Since v.5.8.4 the value of empty_timeout (or no_wait_on_empty) is
2090 * taken into account when `total_time` is specified. It means that
2091 * in the following example the select() returns immediately if
2092 * all mchains are empty:
2093 * \code
2094 * // Creation of extensible-select instance with initial set of cases.
2095 * auto sel = so_5::make_extensible_select(
2096 * so_5::from_all().handle_n(10).no_wait_on_empty().total_time(6s),
2097 * receive_case(ch1, ...),
2098 * receive_case(ch2, ...));
2099 * ...
2100 * so_5::add_select_cases(sel, ...);
2101 * ...
2102 * auto r = select(sel);
2103 * \endcode
2104 *
2105 * \since v.5.6.1
2106 */
2107template<
2108 mchain_props::msg_count_status_t Msg_Count_Status,
2109 typename... Cases >
2110[[nodiscard]]
2113 //! Parameters for advanced select.
2114 mchain_select_params_t< Msg_Count_Status > params,
2115 //! Select cases.
2116 Cases &&... cases )
2117 {
2118 static_assert(
2120 "message count to be processed/extracted should be defined "
2121 "by using handle_all()/handle_n()/extract_n() methods" );
2122
2123 using namespace mchain_props::details;
2124
2128 std::forward<Cases>(cases)... );
2129
2131 std::move(params),
2132 std::move(cases_holder) );
2133
2134 return { std::move(data) };
2135 }
2136
2137/*!
2138 * \brief Add a portion of cases to extensible-select instance.
2139 *
2140 * Usage examples:
2141 * \code
2142 * // Creation of extensible-select instance without initial set of cases.
2143 * auto sel2 = so_5::make_extensible_select(
2144 * so_5::from_all().handle_n(20));
2145 * // Cases should be added later.
2146 * so_5::add_select_cases(sel2, receive_case(ch1, ...));
2147 * so_5::add_select_cases(sel2,
2148 * receive_case(ch2, ...),
2149 * receive_case(ch3, ...));
2150 * \endcode
2151 *
2152 * \note
2153 * An attempt to call this function for extensible-select object that is
2154 * used in some select() call will lead to an exception.
2155 *
2156 * \attention
2157 * The \a extensible_select object must not be empty!
2158 *
2159 * \since v.5.6.1
2160 */
2161template< typename... Cases >
2162void
2164 //! An instance of extensible-select to be extended.
2165 extensible_select_t & extensible_select,
2166 //! Select cases.
2167 Cases &&... cases )
2168 {
2169 using namespace mchain_props::details;
2170
2173 };
2174
2176 locker.cases(),
2177 std::forward<Cases>(cases)... );
2178 }
2179
2180/*!
2181 * \brief A select operation to be done on previously prepared
2182 * extensible-select object.
2183 *
2184 * Usage example:
2185 * \code
2186 * void handle_messages_from(const std::vector<so_5::mchain_t> & chains) {
2187 * auto sel = so_5::make_extensible_select(so_5::from_all().handle_all());
2188 *
2189 * for(auto & ch : chains)
2190 * so_5::add_select_cases(receive_case(ch, ...));
2191 *
2192 * auto r = so_5::select(sel);
2193 * ... // Handing of the select() result.
2194 * }
2195 * \endcode
2196 *
2197 * \note
2198 * An attempt to call this function for extensible-select object that is
2199 * used in some select() call will lead to an exception.
2200 *
2201 * \attention
2202 * The \a extensible_select object must not be empty!
2203 *
2204 * \since v.5.6.1
2205 */
2208 const extensible_select_t & extensible_select )
2209 {
2210 using namespace mchain_props::details;
2211
2213 outliving_mutable(extensible_select.data())
2214 };
2215
2217 locker.params(),
2218 locker.cases() );
2219 }
2220
2221} /* namespace so_5 */
2222
2223#if defined(__clang__) && (__clang_major__ >= 16)
2224#pragma clang diagnostic pop
2225#endif
virtual mbox_id_t id() const =0
Unique ID of this mbox.
A base class for agents.
Definition agent.hpp:673
static demand_handler_pfn_t get_demand_handler_on_message_ptr() noexcept
Definition agent.cpp:1388
const state_t & so_current_state() const
Access to the current agent state.
Definition agent.hpp:934
const mbox_t & so_direct_mbox() const
Get the agent's direct mbox.
Definition agent.cpp:762
static demand_handler_pfn_t get_demand_handler_on_enveloped_msg_ptr() noexcept
Definition agent.cpp:1406
It's a kind of strong typedef for coop's deregistration reason.
Definition coop.hpp:80
Type of smart handle for a cooperation.
Template class for storing bunch of message handlers.
Helper class for calculating remaining time.
An interface of envelope with some message/signal inside.
virtual void access_hook(access_context_t context, handler_invoker_t &invoker) noexcept=0
An extended version of handling_context which can be used for calling event handler.
virtual void invoke(const payload_info_t &payload) noexcept=0
Call an actual handler for the enveloped message/signal.
An information about payload inside envelope.
message_ref_t & message() const noexcept
payload_info_t(message_ref_t message)
Initializing constructor.
Parameters for the SObjectizer Environment initialization.
void event_queue_hook(event_queue_hook_unique_ptr_t hook)
Set event_queue_hook object.
environment_params_t & add_layer(std::unique_ptr< SO_Layer > layer_ptr)
Add an additional layer to the SObjectizer Environment.
environment_params_t()
Constructor.
SObjectizer Environment.
void remove_stop_guard(stop_guard_shptr_t guard)
Remove stop_guard and complete the stop operation if necessary.
stop_guard_t::setup_result_t setup_stop_guard(stop_guard_shptr_t guard, stop_guard_t::what_if_stop_in_progress_t reaction_on_stop_in_progress=stop_guard_t::what_if_stop_in_progress_t::throw_exception)
Set up a new stop_guard.
Interface of event_queue_hook object.
static void noop_deleter(event_queue_hook_t *) noexcept
An implementation of no-op deleter.
An interface of event queue for agent.
virtual void push(execution_demand_t demand)=0
Enqueue new event to the queue.
trigger_t & trigger() const noexcept
Get a reference to activated trigger.
virtual void no_handler_hook(const scenario_in_progress_accessor_t &scenario_accessor, const incident_info_t &info, const message_ref_t &incoming_msg) noexcept=0
abstract_scenario_step_t & operator=(const abstract_scenario_step_t &)=delete
virtual void add_preactivate_action(preactivate_action_t action)=0
Add another preactivation action.
virtual void setup_triggers(trigger_container_t triggers, std::size_t triggers_to_activate) noexcept=0
Setup triggers for the step.
virtual void setup_constraints(constraint_container_t constraints) noexcept=0
Setup constraints for the step.
virtual const std::string & name() const noexcept=0
Get the name of the step.
virtual void post_handler_hook(const scenario_in_progress_accessor_t &scenario_accessor, token_t token) noexcept=0
Hook that should be called just after completion of event-handler.
abstract_scenario_step_t & operator=(abstract_scenario_step_t &&)=delete
virtual void preactivate() noexcept=0
Perform preactivation of the step.
virtual token_t pre_handler_hook(const scenario_in_progress_accessor_t &scenario_accessor, const incident_info_t &info, const message_ref_t &incoming_msg) noexcept=0
Hook that should be called before invocation of event-handler.
abstract_scenario_step_t(const abstract_scenario_step_t &)=delete
virtual status_t status() const noexcept=0
Get the current status of the step.
token_t(abstract_scenario_step_t *activated_step, abstract_scenario_step_t::token_t step_token)
virtual void store_msg_inspection_result(const scenario_in_progress_accessor_t &, const abstract_scenario_step_t &step, const std::string &tag, const std::string &inspection_result)=0
Store msg inspection result in the scenario.
scenario_in_progress_accessor_t make_accessor() noexcept
Helper method for creation of scenario_in_progress_accessor instance.
virtual void run_for(std::chrono::steady_clock::duration run_time)=0
Run the scenario until completion or for specific amount of time.
virtual token_t pre_handler_hook(const incident_info_t &info, const message_ref_t &incoming_msg) noexcept=0
Hook that should be called before invocation of event-handler.
virtual std::string stored_msg_inspection_result(const std::string &step_name, const std::string &tag) const =0
Get a value of stored msg inspection result.
virtual void post_handler_hook(token_t token) noexcept=0
Hook that should be called just after completion of event-handler.
virtual void no_handler_hook(const incident_info_t &info, const message_ref_t &incoming_msg) noexcept=0
abstract_scenario_t & operator=(const abstract_scenario_t &)=delete
virtual void store_state_name(const scenario_in_progress_accessor_t &, const abstract_scenario_step_t &step, const std::string &tag, const std::string &state_name)=0
Store a name of an agent state in the scenario.
virtual bool has_stored_state_name(const std::string &step_name, const std::string &tag) const =0
Check presence of the stored state name.
virtual std::string stored_state_name(const std::string &step_name, const std::string &tag) const =0
Get the stored state name.
abstract_scenario_t & operator=(abstract_scenario_t &&)=delete
virtual scenario_result_t result() const noexcept=0
Get the result of scenario execution.
virtual step_definition_proxy_t define_step(nonempty_name_t step_name)=0
Create a new step and return proxy for it.
abstract_scenario_t(const abstract_scenario_t &)=delete
virtual bool has_stored_msg_inspection_result(const std::string &step_name, const std::string &tag) const =0
Is there the inspection result?
An interface for object that will unfreeze all registered agents when testing scenario starts.
Definition all.cpp:449
agent_unfreezer_t & operator=(const agent_unfreezer_t &)=delete
virtual void unfreeze() noexcept=0
Issue a command to unfreeze all frozen agents.
agent_unfreezer_t & operator=(agent_unfreezer_t &&)=delete
constraint_t & operator=(constraint_t &&)=delete
virtual void start() noexcept=0
Hook for step preactivation.
constraint_t & operator=(const constraint_t &)=delete
virtual bool check(const incident_status_t incident_status, const incident_info_t &info) const noexcept=0
Check for fulfillment of constraint.
virtual void finish() noexcept=0
Hook for step completion.
const agent_t * register_new_catcher(const so_5::mbox_t &from) const
Helper for registration of a new agent.
const std::chrono::steady_clock::duration m_pause
Value to be used.
std::chrono::steady_clock::time_point m_started_at
Time point of step preactivation.
bool check(const incident_status_t, const incident_info_t &) const noexcept override
Check for fulfillment of constraint.
std::chrono::steady_clock::time_point m_started_at
Time point of step preactivation.
const std::chrono::steady_clock::duration m_pause
Value to be used.
bool check(const incident_status_t, const incident_info_t &) const noexcept override
Check for fulfillment of constraint.
preactivate_actions_container_t m_preactivate_actions
All preactivation actions.
Definition all.cpp:143
std::size_t m_triggers_activated
Count of triggers those are activated.
Definition all.cpp:175
void no_handler_hook(const scenario_in_progress_accessor_t &scenario_accessor, const incident_info_t &info, const message_ref_t &incoming_msg) noexcept override
Definition all.cpp:256
token_t pre_handler_hook(const scenario_in_progress_accessor_t &scenario_accessor, const incident_info_t &info, const message_ref_t &incoming_msg) noexcept override
Hook that should be called before invocation of event-handler.
Definition all.cpp:210
bool try_pass_constraints(const incident_status_t incident_status, const incident_info_t &info) const noexcept
An attempt to check constraints for a new incident.
Definition all.cpp:353
void setup_constraints(constraint_container_t constraints) noexcept override
Setup constraints for the step.
Definition all.cpp:301
void preactivate() noexcept override
Perform preactivation of the step.
Definition all.cpp:203
std::size_t m_last_non_activated_trigger
Index of last trigger in the first part of trigger's container.
Definition all.cpp:166
status_t status() const noexcept override
Get the current status of the step.
Definition all.cpp:273
std::size_t m_triggers_to_completion
Count of activated triggers those are not completed yet.
Definition all.cpp:184
status_t m_status
The current state of the step.
Definition all.cpp:187
void post_handler_hook(const scenario_in_progress_accessor_t &scenario_accessor, token_t token) noexcept override
Hook that should be called just after completion of event-handler.
Definition all.cpp:230
const std::string & name() const noexcept override
Get the name of the step.
Definition all.cpp:197
token_t try_activate(const trigger_activation_context_t &context, const incident_status_t incident_status, const incident_info_t &info) noexcept
An attempt to activate the step when a new incident arrives.
Definition all.cpp:367
constraint_container_t m_constraints
All constraints.
Definition all.cpp:146
void add_preactivate_action(preactivate_action_t action) override
Add another preactivation action.
Definition all.cpp:279
void setup_triggers(trigger_container_t triggers, std::size_t triggers_to_activate) noexcept override
Setup triggers for the step.
Definition all.cpp:286
void no_handler_hook(const incident_info_t &info, const message_ref_t &incoming_msg) noexcept override
Definition all.cpp:656
std::string stored_msg_inspection_result(const std::string &step_name, const std::string &tag) const override
Get a value of stored msg inspection result.
Definition all.cpp:737
bool has_stored_state_name(const std::string &step_name, const std::string &tag) const override
Check presence of the stored state name.
Definition all.cpp:719
std::size_t m_waiting_step_index
Index of the current preactivated step.
Definition all.cpp:499
std::set< abstract_scenario_step_t * > m_active_steps
Set of active step those are not completed yet.
Definition all.cpp:496
scenario_result_t result() const noexcept override
Get the result of scenario execution.
Definition all.cpp:566
void store_msg_inspection_result(const scenario_in_progress_accessor_t &, const abstract_scenario_step_t &step, const std::string &tag, const std::string &inspection_result) override
Store msg inspection result in the scenario.
Definition all.cpp:682
bool has_stored_msg_inspection_result(const std::string &step_name, const std::string &tag) const override
Is there the inspection result?
Definition all.cpp:762
std::string stored_state_name(const std::string &step_name, const std::string &tag) const override
Get the stored state name.
Definition all.cpp:694
token_t react_on_pre_handler_hook(const incident_info_t &info, const message_ref_t &incoming_msg) noexcept
Definition all.cpp:789
std::condition_variable m_completion_cv
Condition variable for waiting completion of the scenario.
Definition all.cpp:480
void react_on_no_handler_hook(const incident_info_t &info, const message_ref_t &incoming_msg) noexcept
Definition all.cpp:833
void post_handler_hook(token_t token) noexcept override
Hook that should be called just after completion of event-handler.
Definition all.cpp:627
void run_for(std::chrono::steady_clock::duration run_time) override
Run the scenario until completion or for specific amount of time.
Definition all.cpp:577
agent_unfreezer_t * m_unfreezer
Unfreezer for registered agents.
Definition all.cpp:530
void setup_unfreezer(agent_unfreezer_t &unfreezer) noexcept
Set the unfreezer for registered agents.
Definition all.cpp:541
inspection_result_map_t m_stored_inspection_results
Container for holding stored inspection results for messages.
Definition all.cpp:524
void store_state_name(const scenario_in_progress_accessor_t &, const abstract_scenario_step_t &step, const std::string &tag, const std::string &state_name) override
Store a name of an agent state in the scenario.
Definition all.cpp:672
token_t pre_handler_hook(const incident_info_t &info, const message_ref_t &incoming_msg) noexcept override
Hook that should be called before invocation of event-handler.
Definition all.cpp:607
step_definition_proxy_t define_step(nonempty_name_t step_name) override
Create a new step and return proxy for it.
Definition all.cpp:548
state_name_map_t m_stored_states
Container for holding stored state names.
Definition all.cpp:518
scenario_status_t m_status
The current state of the scenario.
Definition all.cpp:483
std::vector< step_unique_ptr_t > m_steps
Scenario's steps.
Definition all.cpp:489
scenario_in_progress_accessor_t & operator=(scenario_in_progress_accessor_t &&)=delete
scenario_in_progress_accessor_t(outliving_reference_t< abstract_scenario_t > scenario)
scenario_in_progress_accessor_t(scenario_in_progress_accessor_t &&)=delete
scenario_in_progress_accessor_t & operator=(const scenario_in_progress_accessor_t &)=delete
scenario_in_progress_accessor_t(const scenario_in_progress_accessor_t &)=delete
trigger_holder_t & operator=(trigger_holder_t &&) noexcept=default
trigger_holder_t & operator=(const trigger_holder_t &)=delete
trigger_holder_t(trigger_holder_t &&) noexcept=default
trigger_unique_ptr_t giveout_trigger() noexcept
Get the trigger object from the holder.
activation_function_t m_activation
Optional function for activation of the trigger.
const std::type_index m_msg_type
Type of message/signal to activate the trigger.
completion_function_t m_completion
Optional function for completion of the trigger.
void set_completion(completion_function_t fn)
Setter for completion function.
Definition all.cpp:51
void set_activation(activation_function_t fn)
Setter for activation function.
Definition all.cpp:73
void activate(const trigger_activation_context_t &context) noexcept
Do activation of the trigger.
Definition all.cpp:114
bool check(const incident_status_t incident_status, const incident_info_t &info) const noexcept
Check for activation of the trigger.
Definition all.cpp:96
const mbox_id_t m_src_mbox_id
ID of source mbox of message/signal to activate the trigger.
trigger_t(incident_status_t incident_status, const agent_t &target, std::type_index msg_type, mbox_id_t src_mbox_id)
Initializing constructor.
Definition all.cpp:28
const agent_t & target_agent() const noexcept
Get the reference of the target agent.
Definition all.cpp:45
const incident_status_t m_incident_status
What should happen with initial message/signal.
bool requires_completion() const noexcept
Does this trigger require separate completion action?
Definition all.cpp:108
const mbox_id_t m_target_id
The unique ID of target's direct mbox.
void complete(const trigger_completion_context_t &context) noexcept
Do completion of a trigger.
Definition all.cpp:122
const agent_t & m_target_agent
A reference to the target agent.
outliving_reference_t< so_5::enveloped_msg::handler_invoker_t > m_invoker
Handler invoker that has to be used for extracted message.
Definition all.cpp:1079
invoker_for_message_extraction_t(outliving_reference_t< so_5::enveloped_msg::handler_invoker_t > invoker, so_5::enveloped_msg::access_context_t access_context)
Initializing constructor.
Definition all.cpp:1089
const so_5::enveloped_msg::access_context_t m_access_context
Context for accessing enveloped message.
Definition all.cpp:1082
bool handled() const noexcept
Has the message actually been handled?
Definition all.cpp:1128
void invoke(const so_5::enveloped_msg::payload_info_t &payload) noexcept override
Call an actual handler for the enveloped message/signal.
Definition all.cpp:1099
void invoke(const payload_info_t &payload) noexcept override
Call an actual handler for the enveloped message/signal.
Definition all.cpp:1061
no_handler_invoker_t(outliving_reference_t< special_envelope_t > owner)
Initializing constructor.
Definition all.cpp:1055
outliving_reference_t< special_envelope_t > m_owner
Owner of this invoker.
Definition all.cpp:1051
outliving_reference_t< handler_invoker_t > m_actual_invoker
Invoker to be used to call the actual event handler.
Definition all.cpp:1016
void invoke(const payload_info_t &payload) noexcept override
Call an actual handler for the enveloped message/signal.
Definition all.cpp:1030
pre_handler_hook_invoker_t(outliving_reference_t< special_envelope_t > owner, outliving_reference_t< handler_invoker_t > actual_invoker)
Intializing constructor.
Definition all.cpp:1020
outliving_reference_t< special_envelope_t > m_owner
Owner of this invoker.
Definition all.cpp:1013
outliving_reference_t< details::abstract_scenario_t > m_scenario
A testing scenario for that envelope.
Definition all.cpp:1000
special_envelope_t(outliving_reference_t< details::abstract_scenario_t > scenario, const execution_demand_t &demand)
Initializing constructor.
Definition all.cpp:1136
details::incident_info_t m_demand_info
Information about enveloped message.
Definition all.cpp:1002
void access_hook(access_context_t context, handler_invoker_t &invoker) noexcept override
Definition all.cpp:1165
delivery_result_t m_delivery_result
Was this message handled by a receiver?
Definition all.cpp:1007
void unfreeze() noexcept override
Issue a command to unfreeze all frozen agents.
Definition all.cpp:1490
outliving_reference_t< details::abstract_scenario_t > m_scenario
Testing scenario for that this object is created.
Definition all.cpp:1440
void on_unbind(agent_t *, event_queue_t *queue) noexcept override
A reaction to unbinding of an agent from some event_queue.
Definition all.cpp:1480
queue_mode_t m_mode
Mode of operation for new queues.
Definition all.cpp:1437
std::vector< special_event_queue_t * > m_created_queues
List of all queues created before unfreeze was called.
Definition all.cpp:1452
special_event_queue_hook_t(outliving_reference_t< details::abstract_scenario_t > scenario)
Definition all.cpp:1455
event_queue_t * on_bind(agent_t *, event_queue_t *original_queue) noexcept override
A reaction to binding of an agent to some event_queue.
Definition all.cpp:1462
std::vector< execution_demand_t > m_buffer
Local storage for demands to be used in buffered mode.
Definition all.cpp:1280
static bool is_ordinary_demand(const execution_demand_t &demand) noexcept
Definition all.cpp:1283
special_event_queue_t(outliving_reference_t< details::abstract_scenario_t > scenario, outliving_reference_t< event_queue_t > original_queue, queue_mode_t queue_mode)
Definition all.cpp:1303
void push_evt_finish(execution_demand_t demand) noexcept override
Enqueue a demand for evt_finish event.
Definition all.cpp:1344
queue_mode_t m_mode
The current mode of operation.
Definition all.cpp:1278
void push_evt_start(execution_demand_t demand) override
Enqueue a demand for evt_start event.
Definition all.cpp:1337
outliving_reference_t< event_queue_t > m_original_queue
Original event_queue.
Definition all.cpp:1275
void push(execution_demand_t demand) override
Enqueue new event to the queue.
Definition all.cpp:1313
outliving_reference_t< details::abstract_scenario_t > m_scenario
Testing scenario for that this queue was created.
Definition all.cpp:1273
stop_guard_for_unfreezer_t(outliving_reference_t< details::agent_unfreezer_t > unfreezer, outliving_reference_t< environment_t > env)
Definition all.cpp:1396
outliving_reference_t< details::agent_unfreezer_t > m_unfreezer
Definition all.cpp:1392
void stop() noexcept override
Perform stop-related actions.
Definition all.cpp:1404
step_definition_proxy_t define_step(nonempty_name_t step_name)
Start definition of a new scenario's step.
Definition all.cpp:1608
std::string stored_state_name(const std::string &step_name, const std::string &tag) const
Try to get stored name of an agent's state.
Definition all.cpp:1628
std::string stored_msg_inspection_result(const std::string &step_name, const std::string &tag) const
Try to get stored msg inspection result.
Definition all.cpp:1644
outliving_reference_t< details::abstract_scenario_t > m_scenario
bool has_stored_state_name(const std::string &step_name, const std::string &tag) const
Is there the inspection result?
Definition all.cpp:1636
bool has_stored_msg_inspection_result(const std::string &step_name, const std::string &tag) const
Is there the inspection result?
Definition all.cpp:1652
void run_for(std::chrono::steady_clock::duration run_time)
Runs the scenario for specified amount of time.
Definition all.cpp:1621
scenario_proxy_t(outliving_reference_t< details::abstract_scenario_t > scenario)
Definition all.cpp:1602
scenario_result_t result() const
Get the result of scenario execution.
Definition all.cpp:1615
scenario_result_t(scenario_status_t status)
The constructor for a case when there is only status of scenario.
scenario_result_t(scenario_status_t status, std::string description)
bool operator!=(const scenario_result_t &o) const noexcept
Check for inequality.
bool operator==(const scenario_result_t &o) const noexcept
Check for equality.
A special object that should be used for definition of a step of a testing scenario.
step_definition_proxy_t(details::abstract_scenario_step_t *step)
Initializing constructor.
step_definition_proxy_t & impact(Lambda &&lambda)
Add preactivation action in form of lambda-object.
step_definition_proxy_t & when_all(details::trigger_holder_t< Status > event, Args &&...args)
Add a list of tiggers for activation of that step.
void append_trigger_to(details::trigger_container_t &to, details::trigger_holder_t< Status > event, Args &&...args)
void append_constraint_to(details::constraint_container_t &to, details::constraint_unique_ptr_t head, Args &&...tail)
step_definition_proxy_t & impact(Target &&target, Args &&...args)
Define a preactivation action in form of sending a message/signal to the specified target.
step_definition_proxy_t & constraints(details::constraint_unique_ptr_t head, Args &&...tail)
Add a list of constraints for that step.
step_definition_proxy_t & when_any(details::trigger_holder_t< Status > event, Args &&...args)
Add a list of tiggers for activation of that step.
step_definition_proxy_t & when(details::trigger_holder_t< Status > event)
Add a tigger for activation of that step.
A special testing environment that should be used for testing of agents.
void stop()
Send stop signal to environment.
Definition all.cpp:1694
environment_t & environment() const
Access to wrapped environment.
Definition all.cpp:1688
testing_env_t(environment_params_t &&env_params)
Definition all.cpp:1671
scenario_proxy_t scenario() noexcept
Access to the associated scenario.
Definition all.cpp:1713
void join()
Wait for complete finish of environment's work.
Definition all.cpp:1700
void tune_environment_on_start(environment_t &env)
Definition all.cpp:1719
void stop_then_join()
Send stop signal and wait for complete finish of environment's work.
Definition all.cpp:1706
testing_env_t(so_5::generic_simple_so_env_params_tuner_t env_params_tuner)
A constructor that allows to tune environment's parameters.
Definition all.cpp:1666
Special container for holding select parameters and select cases.
extensible_select_t & operator=(extensible_select_t &&other) noexcept
Move operator.
extensible_select_t()=default
Default constructor.
extensible_select_t(extensible_select_t &&other) noexcept
Move constructor.
friend void swap(extensible_select_t &a, extensible_select_t &b) noexcept
Swap operation.
bool empty() const noexcept
Is this handle empty?
std::unique_ptr< mchain_props::details::extensible_select_data_t > m_data
Actual data for that extensible-select.
auto & data() const noexcept
extensible_select_t & operator=(const extensible_select_t &)=delete
extensible_select_t(const extensible_select_t &)=delete
extensible_select_t(std::unique_ptr< mchain_props::details::extensible_select_data_t > data)
Actual initializing constructor.
friend extensible_select_t make_extensible_select(mchain_select_params_t< Msg_Count_Status > params, Cases &&... cases)
Creation of extensible-select instance.
intrusive_ptr_t(intrusive_ptr_t &&o) noexcept
Move constructor.
T * operator->() const noexcept
intrusive_ptr_t(const intrusive_ptr_t &o) noexcept
Copy constructor.
intrusive_ptr_t & operator=(intrusive_ptr_t &&o) noexcept
Move operator.
An interface of the additional SObjectizer Environment layer.
Definition so_layer.hpp:31
Basic parameters for advanced receive from mchain and for multi chain select.
Definition mchain.hpp:1215
Actual implementation of one multi chain select case.
actual_receive_select_case_t(mchain_t chain, Handlers &&... handlers)
Initializing constructor.
mchain_receive_result_t try_handle_extracted_message(demand_t &demand) override
Attempt to handle extracted message.
Actual implementation of notificator for multi chain select.
select_case_t * m_tail
Queue of already notified select_cases.
actual_select_notificator_t(Fwd_it b, Fwd_it e)
Initializing constructor.
void push_to_notified_chain(select_case_t &what) noexcept
select_case_t * wait(duration_t wait_time)
Wait for any notified select_case.
void return_to_ready_chain(select_case_t &what) noexcept
Return specifed select_case object to the chain of 'notified select_cases'.
void notify(select_case_t &what) noexcept override
The actual implementation of select_case for the case of sending a message.
void on_successful_push() override
Hook for handling successful push attempt.
actual_send_select_case_t(mchain_t chain, std::type_index msg_type, message_ref_t message, const On_Success_Handler &success_handler)
Initializing constructor for the case when success_handler is a const lvalue.
On_Success_Handler m_success_handler
Actual handler of successful send attempt.
actual_send_select_case_t(mchain_t chain, std::type_index msg_type, message_ref_t message, On_Success_Handler &&success_handler)
Initializing constructor for the case when success_handler is a rvalue.
A holder for serie of select_cases for the case of extensible select.
extensible_select_cases_holder_t(const extensible_select_cases_holder_t &)=delete
extensible_select_cases_holder_t & operator=(extensible_select_cases_holder_t &&o) noexcept
Move operator.
extensible_select_cases_holder_t & operator=(const extensible_select_cases_holder_t &)=delete
extensible_select_cases_holder_t(extensible_select_cases_holder_t &&o) noexcept
Move constructor.
friend void swap(extensible_select_cases_holder_t &a, extensible_select_cases_holder_t &b) noexcept
Swap operation.
extensible_select_cases_holder_t(std::size_t initial_capacity)
Constructor with initial capacity.
const_iterator end() const noexcept
Get iterator for the item just behind the last item in select_cases_holder.
std::size_t size() const noexcept
Get count of select_cases in holder.
const_iterator begin() const noexcept
Get iterator for the first item in select_cases_holder.
void add_case(select_case_unique_ptr_t c)
Helper method for setting up specific select_case.
Special class for locking extensible-select instance for activation inside select() call.
Special class for locking extensible-select instance for modification.
const mchain_select_params_t< mchain_props::msg_count_status_t::defined > m_params
Parameters for select.
extensible_select_status_t m_status
The current status of extensible-select object.
extensible_select_cases_holder_t m_cases
A list of cases for extensible-select operation.
extensible_select_data_t(const extensible_select_data_t &)=delete
extensible_select_data_t(extensible_select_data_t &&)=delete
extensible_select_data_t(mchain_select_params_t< msg_count_status_t::defined > &&params, extensible_select_cases_holder_t &&cases) noexcept
Initializing constructor.
std::size_t to_handle() const noexcept
Get limit for count of message to be handled.
Definition mchain.hpp:1170
const mchain_props::duration_t & total_time() const noexcept
Get total time for the whole receive operation.
Definition mchain.hpp:1178
const stop_predicate_t & stop_on() const noexcept
Get user condition for stopping receive operation.
Definition mchain.hpp:1182
std::size_t to_extract() const noexcept
Get limit for count of messages to be extracted.
Definition mchain.hpp:1166
const chain_closed_handler_t & closed_handler() const noexcept
Get handler for chain-closed event.
Definition mchain.hpp:1189
const mchain_props::duration_t & empty_timeout() const noexcept
Get timeout for waiting on empty chain.
Definition mchain.hpp:1174
Special class for locking prepared-select instance for activation inside select() call.
prepared_select_data_t(mchain_select_params_t< msg_count_status_t::defined > &&params, Cases &&...cases) noexcept
Initializing constructor.
prepared_select_data_t(prepared_select_data_t &&)=delete
select_cases_holder_t< Cases_Count > m_cases
A list of cases for extensible-select operation.
prepared_select_data_t(const prepared_select_data_t &)=delete
prepared_select_status_t m_status
The current status of extensible-select object.
const mchain_select_params_t< mchain_props::msg_count_status_t::defined > m_params
Parameters for select.
A base class for implementations of select_case for the case of receiving messages.
virtual mchain_receive_result_t try_handle_extracted_message(demand_t &demand)=0
Attempt to handle extracted message.
handling_result_t try_handle(select_notificator_t &notificator) override
An attempt to handle this case.
Helper class for performing select-specific operations.
const mchain_select_params_t< msg_count_status_t::defined > & m_params
void on_send_result(select_case_t *current, const mchain_send_result_t &result)
extraction_status_t last_extraction_status() const noexcept
std::size_t m_completed_send_cases
The counter of completed send_cases.
void on_receive_result(select_case_t *current, const mchain_receive_result_t &result)
mchain_select_result_t make_result() const noexcept
select_actions_performer_t(const mchain_select_params_t< msg_count_status_t::defined > &params, const Holder &select_cases)
bool operator!=(const const_iterator &o) const noexcept
bool operator==(const const_iterator &o) const noexcept
select_cases_holder_t & operator=(select_cases_holder_t &&o) noexcept
Move operator.
void set_case(std::size_t index, select_case_unique_ptr_t c) noexcept
Helper method for setting up specific select_case.
const_iterator end() const noexcept
Get iterator for the item just behind the last item in select_cases_holder.
select_cases_holder_t(const select_cases_holder_t &)=delete
friend void swap(select_cases_holder_t &a, select_cases_holder_t &b) noexcept
Swap operation.
const_iterator begin() const noexcept
Get iterator for the first item in select_cases_holder.
select_cases_holder_t(select_cases_holder_t &&o) noexcept
Move constructor.
array_type_t m_cases
Storage for select_cases.
select_cases_holder_t & operator=(const select_cases_holder_t &)=delete
std::size_t size() const noexcept
Get count of select_cases in holder.
A base class for implementations of select_case for the case of sending messages.
std::type_index m_msg_type
Type of message to be sent.
virtual void on_successful_push()=0
Hook for handling successful push attempt.
send_select_case_t(mchain_t chain, std::type_index msg_type, message_ref_t message)
Initializing constructor.
message_ref_t m_message
Message to be sent.
handling_result_t try_handle(select_notificator_t &notificator) override
An attempt to handle this case.
Base class for representation of one case in multi chain select.
const mchain_t & chain() const noexcept
Get the underlying mchain.
auto push(const std::type_index &msg_type, const message_ref_t &message)
Helper method for calling push method of the target mchain.
auto extract(demand_t &demand)
Helper method for calling extract method of the target mchain.
void set_next(select_case_t *next) noexcept
Set the next item in the current queue to which select_case belongs.
select_case_t(mchain_t chain)
Initialized constructor.
select_case_t * giveout_next() noexcept
virtual handling_result_t try_handle(select_notificator_t &notificator)=0
An attempt to handle this case.
select_notificator_t * m_notificator
Notificator to be used for notify sleeping thread.
An interface of select_case notificator.
A result of receive from mchain.
Definition mchain.hpp:922
std::size_t extracted() const noexcept
Count of extracted messages.
Definition mchain.hpp:954
mchain_props::extraction_status_t status() const noexcept
Extraction status (e.g. no messages, chain closed and so on).
Definition mchain.hpp:964
std::size_t handled() const noexcept
Count of handled messages.
Definition mchain.hpp:959
mchain_receive_result_t(std::size_t extracted, std::size_t handled, mchain_props::extraction_status_t status) noexcept
Initializing constructor.
Definition mchain.hpp:939
mchain_select_params_t(typename base_type::data_type data)
Initializing constructor for the case of cloning.
mchain_select_params_t()=default
The default constructor.
decltype(auto) so5_clone_if_necessary() noexcept
A result of select from several mchains.
std::size_t m_closed
Count of closed chains.
std::size_t m_handled
Count of handled incoming messages.
std::size_t handled() const noexcept
Count of handled incoming messages.
bool was_extracted() const noexcept
mchain_select_result_t(std::size_t extracted, std::size_t handled, std::size_t sent, std::size_t closed) noexcept
Initializing constructor.
mchain_select_result_t() noexcept
Default constructor.
std::size_t m_sent
Count of messages sent.
bool was_sent_or_received() const noexcept
std::size_t closed() const noexcept
Count of closed chains.
std::size_t sent() const noexcept
Count of messages sent.
bool was_closed() const noexcept
std::size_t m_extracted
Count of extracted incoming messages.
std::size_t extracted() const noexcept
Count of extracted incoming messages.
bool was_sent() const noexcept
bool was_handled() const noexcept
A result of attempt of sending messages to a message chain.
Definition mchain.hpp:979
mchain_props::push_status_t status() const noexcept
Status of send operation.
Definition mchain.hpp:1012
mchain_send_result_t(std::size_t sent, mchain_props::push_status_t status)
Initializing constructor.
Definition mchain.hpp:997
std::size_t sent() const noexcept
Count of messages sent.
Definition mchain.hpp:1007
A class for holding an instance of a message.
A base class for agent messages.
Definition message.hpp:47
friend message_kind_t message_kind(const so_5::intrusive_ptr_t< message_t > &what)
Helper method for quering kind of the message.
Definition message.hpp:154
A class for the name which cannot be empty.
std::string giveout_value() noexcept(noexcept(std::string{ std::move(m_nonempty_name) }))
Get the value away from the object.
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
Special container for holding select parameters and select cases.
auto & data() const noexcept
friend prepared_select_t< sizeof...(Cases) > prepare_select(mchain_select_params_t< Msg_Count_Status > params, Cases &&... cases)
Create prepared select statement to be used later.
prepared_select_t & operator=(prepared_select_t &&other) noexcept
Move operator.
prepared_select_t(prepared_select_t &&other) noexcept
Move constructor.
prepared_select_t & operator=(const prepared_select_t &)=delete
std::unique_ptr< mchain_props::details::prepared_select_data_t< Cases_Count > > m_data
The actual prepared-select object.
prepared_select_t(mchain_select_params_t< mchain_props::msg_count_status_t::defined > params, Cases &&... cases)
Initializing constructor.
prepared_select_t(const prepared_select_t &)=delete
bool empty() const noexcept
Is this handle empty?
friend void swap(prepared_select_t &a, prepared_select_t &b) noexcept
Swap operation.
std::string query_name() const
Get textual name of the state.
Definition agent.cpp:409
An interface of stop_guard entity.
A wrapped environment.
void stop()
Send stop signal to environment.
void stop_then_join()
Send stop signal and wait for complete finish of environment's work.
wrapped_env_t(so_5::generic_simple_init_t init_func, environment_params_t &&params)
void join()
Wait for complete finish of environment's work.
environment_t & environment() const
Access to wrapped environment.
#define SO_5_TYPE
Definition declspec.hpp:46
#define SO_5_THROW_EXCEPTION(error_code, desc)
Definition exception.hpp:74
Some reusable and low-level classes/functions which can be used in public header files.
bool wait_for_big_interval(std::unique_lock< std::mutex > &lock, std::condition_variable &cv, std::chrono::steady_clock::duration timeout, Predicate pred)
Helper function for safe call of condition_variable::wait_for with possible big timeouts.
auto invoke_noexcept_code(L lambda) noexcept -> decltype(lambda())
envelope_t & message_to_envelope(const message_ref_t &src_msg)
A helper function for casting message instance to envelope instance.
access_context_t
Information about context on that enveloped message is handled.
trigger_holder_t< incident_status_t::handled > operator&(trigger_holder_t< incident_status_t::handled > &&old_holder, wait_event_handler_completion_t)
A helper operator to create a tigger that requires the completion of an event handler.
trigger_holder_t< Status > operator&(trigger_holder_t< Status > &&old_holder, store_msg_inspection_result_t inspection_info)
A helper operator to create a tigger that inspects the incoming message and stores the result into th...
trigger_holder_t< incident_status_t::handled > operator&(const mbox_t &from, receives_indicator_t< Msg >)
A helper operator to create a tigger that receives a message/signal from specified mbox.
trigger_holder_t< Status > operator&(const so_5::agent_t &agent, const trigger_source_t< Status > &src)
A helper operator to create a trigger for the specified agent.
incident_status_t
What happened with source of an event.
trigger_holder_t< incident_status_t::handled > operator&(trigger_holder_t< incident_status_t::handled > &&old_holder, store_agent_state_name_t data_to_store)
A helper operator to create a tigger that stores the name of the current agent's state.
environment_params_t make_special_params(outliving_reference_t< testing_env_t::internals_t > internals, environment_params_t &&params)
Definition all.cpp:1582
void setup_special_queue_hook(outliving_reference_t< testing_env_t::internals_t > internals, environment_params_t &to)
Definition all.cpp:1558
environment_params_t make_tuned_params(so_5::generic_simple_so_env_params_tuner_t env_params_tuner)
Definition all.cpp:1571
queue_mode_t
A mode of work for special_event_queue.
Definition all.cpp:1224
@ direct
All messages should go to the original queue without buffering.
@ buffer
All messages must be stored locally.
scenario_result_t completed()
Create a value that means that scenario completed successfuly.
details::receives_indicator_t< Msg > receives()
Helper function to be used for a trigger that receives a message/singal from a mbox.
details::trigger_source_t< details::incident_status_t::ignored > ignores()
Define a trigger that activates when an agent rejects a message from the direct mbox.
@ completed
Testing scenario is successfuly completed.
details::constraint_unique_ptr_t not_after(std::chrono::steady_clock::duration pause)
Create a constraint not-after.
details::store_msg_inspection_result_t inspect_msg(std::string tag, Lambda &&inspector)
Create a special marker for a trigger for inspecting an incoming message and storing the inspection r...
details::store_agent_state_name_t store_state_name(std::string tag)
Create a special marker for a trigger for storing agent's state name inside scenario.
details::trigger_source_t< details::incident_status_t::handled > reacts_to()
Define a trigger that activates when an agent receives and handles a message from the direct mbox.
details::trigger_source_t< details::incident_status_t::handled > reacts_to(const so_5::mbox_t &mbox)
Define a trigger that activates when an agent receives and handles a message from the specific mbox.
details::constraint_unique_ptr_t not_before(std::chrono::steady_clock::duration pause)
Create a constraint not-before.
details::trigger_source_t< details::incident_status_t::ignored > ignores(const so_5::mbox_t &mbox)
Define a trigger that activates when an agent rejects a message from the direct mbox.
details::wait_event_handler_completion_t wait_event_handler_completion()
Create a special marker for a trigger that requires waiting for completion of an event handler.
Implementation details.
Definition mchain.hpp:37
bool is_infinite_wait_timevalue(duration_t v)
Is time value means 'infinite_wait'?
Definition mchain.hpp:84
void fill_select_cases_holder(extensible_select_cases_holder_t &holder, select_case_unique_ptr_t c, Cases &&... other_cases)
mchain_select_result_t perform_select(const mchain_select_params_t< msg_count_status_t::defined > &params, const Cases_Holder &cases_holder)
Helper function with implementation of main select action.
prepared_select_status_t
The current status of prepared-select instance.
@ passive
Prepared-select instance is not used in select() call.
@ active
Prepared-select instance is used in select() call now.
void fill_select_cases_holder(Holder &holder, std::size_t index, select_case_unique_ptr_t c, Cases &&... other_cases)
mchain_select_result_t do_adv_select_without_total_time(const mchain_select_params_t< msg_count_status_t::defined > &params, const Holder &select_cases)
extensible_select_status_t
The current status of extensible-select instance.
@ passive
Extensible-select instance is not used in select() call.
@ active
Extensible-select instance is used in select() call now.
void fill_select_cases_holder(Holder &holder, std::size_t index, select_case_unique_ptr_t c)
mchain_select_result_t do_adv_select_with_total_time(const mchain_select_params_t< msg_count_status_t::defined > &params, const Holder &select_cases)
void fill_select_cases_holder(extensible_select_cases_holder_t &)
Various properties and parameters of message chains.
Definition mchain.hpp:28
msg_count_status_t
Status of limit for messages to be extracted/handled during a bulk operation on a mchain.
Definition mchain.hpp:1027
@ undefined
Message count limit is not set yet.
@ defined
Message count limit is set.
extraction_status_t
Result of extraction of message from a message chain.
Definition mchain.hpp:371
@ msg_extracted
Message extracted successfully.
@ chain_closed
Message cannot be extracted because chain is closed.
@ no_messages
No available messages in the chain.
push_status_t
Result of attempt of pushing a message into a message chain.
Definition mchain.hpp:389
@ not_stored
Message wasn't stored.
@ stored
Message stored into a message chain.
@ chain_closed
Message wasn't stored because chain is closed.
Private part of message limit implementation.
Definition agent.cpp:33
auto make_coop_reg_notificator(mbox_t target) noexcept
Create notificator about cooperation registration completion.
const int rc_scenario_must_be_completed
Testing scenario must be completed before an attempt to do the current operation.
Definition ret_code.hpp:367
const int rc_extensible_select_is_active_now
An attempt to modify or activate extensible-select when an operation on that extensible-select object...
Definition ret_code.hpp:410
void add_select_cases(extensible_select_t &extensible_select, Cases &&... cases)
Add a portion of cases to extensible-select instance.
mchain_select_params_t< mchain_props::msg_count_status_t::undefined > from_all()
Helper function for creation of mchain_select_params instance with default values.
mchain_select_result_t select(const mchain_select_params_t< Msg_Count_Status > &params, Cases &&... cases)
An advanced form of multi chain select.
const int rc_stored_msg_inspection_result_not_found
There is no stored msg inspection result in the testing scenario.
Definition ret_code.hpp:526
@ user_type_message
Message is an user type message.
@ enveloped_msg
Message is an envelope with some other message inside.
mchain_select_result_t select(const extensible_select_t &extensible_select)
A select operation to be done on previously prepared extensible-select object.
const int rc_stored_state_name_not_found
There is no stored state name in the testing scenario.
Definition ret_code.hpp:374
void send(Target &&to, Args &&... args)
A utility function for creating and delivering a message or a signal.
const int rc_unable_to_define_new_step
New step can't be defined if testing scenario is already started or finished.
Definition ret_code.hpp:359
message_ownership_t
Type of ownership of a message instance inside message_holder.
mchain_props::select_case_unique_ptr_t receive_case(mchain_t chain, Handlers &&... handlers)
A helper for creation of select_case object for one multi chain select.
mchain_props::select_case_unique_ptr_t send_case(mchain_t chain, message_holder_t< Msg, Ownership > msg, On_Success_Handler &&handler)
A helper for creation of select_case object for one send-case of a multi chain select.
mchain_select_result_t select(const prepared_select_t< Cases_Count > &prepared)
A select operation to be done on previously prepared select params.
auto make_coop_dereg_notificator(mbox_t target) noexcept
Create notificator about cooperation deregistration completion.
outliving_reference_t< T > outliving_mutable(T &r)
Make outliving_reference wrapper for mutable reference.
prepared_select_t< sizeof...(Cases) > prepare_select(mchain_select_params_t< Msg_Count_Status > params, Cases &&... cases)
Create prepared select statement to be used later.
A description of event execution demand.
mbox_id_t m_mbox_id
ID of mbox.
demand_handler_pfn_t m_demand_handler
Demand handler.
agent_t * m_receiver
Receiver of demand.
message_ref_t m_message_ref
Event incident.
std::type_index m_msg_type
Type of the message.
const std::type_index m_msg_type
Type of message or signal.
incident_info_t(const agent_t *agent, const std::type_index &msg_type, mbox_id_t src_mbox_id)
mbox_id_t m_src_mbox_id
ID of mbox from that message/signal was received.
Special indicator to be used in implementation of receives trigger.
A special data object for case of store-state-name completion action.
A special data object for case when a message inspector has to be used on an incoming message.
std::function< std::string(const message_ref_t &) > m_inspector
Inspector for a message.
Description of context on that an attempt to activate a trigger is performing.
const scenario_in_progress_accessor_t & m_scenario_accessor
Access to the running scenario.
abstract_scenario_step_t & m_step
The current step for that activation is being performed.
trigger_source_t(std::type_index msg_type, mbox_id_t src_mbox_id)
A special data object for case when a step should be completed only after returning from the event ha...
A helper object for synchronization between helper worker where testing environment is launched and u...
Definition all.cpp:1525
Internal data for testing environment.
Definition all.cpp:1538
impl::special_event_queue_hook_t m_special_hook
Definition all.cpp:1540
static std::unique_ptr< internals_t > make()
Definition all.cpp:1552
Description of one demand in message chain.
Definition mchain.hpp:144
A helper class for detection of payload type of message.
Definition message.hpp:783
Message about cooperation deregistration completion.
msg_coop_deregistered(coop_handle_t coop, coop_dereg_reason_t reason) noexcept
msg_coop_deregistered & operator=(const msg_coop_deregistered &)=delete
msg_coop_deregistered(const msg_coop_deregistered &)=delete
msg_coop_deregistered & operator=(msg_coop_deregistered &&)=delete
msg_coop_deregistered(msg_coop_deregistered &&)=delete
Message about cooperation registration completion.
msg_coop_registered & operator=(msg_coop_registered &&)=delete
msg_coop_registered(const msg_coop_registered &)=delete
msg_coop_registered(coop_handle_t coop) noexcept
msg_coop_registered & operator=(const msg_coop_registered &)=delete
msg_coop_registered(msg_coop_registered &&)=delete