SObjectizer-5 Extra
time_unlimited.hpp
Go to the documentation of this file.
1 /*!
2  * \file
3  * \brief Implementation of time-unlimited asynchronous one-time operation.
4  *
5  * \since
6  * v.1.0.4
7  */
8 
9 #pragma once
10 
11 #include <so_5_extra/async_op/details.hpp>
12 #include <so_5_extra/async_op/errors.hpp>
13 
14 #include <so_5/details/invoke_noexcept_code.hpp>
15 
16 #include <so_5/agent.hpp>
17 
18 #include <so_5/outliving.hpp>
19 
20 #include <vector>
21 
22 namespace so_5 {
23 
24 namespace extra {
25 
26 namespace async_op {
27 
28 namespace time_unlimited {
29 
30 //! Enumeration for status of operation.
31 enum class status_t
32  {
33  //! Status of operation is unknown because the
34  //! operation data has been moved to another proxy-object.
36  //! Operation is not activated yet.
38  //! Operation is activated.
39  activated,
40  //! Operation is completed.
41  completed,
42  //! Operation is cancelled.
43  cancelled
44  };
45 
46 // Forward declarations.
47 // Necessary to declare friends for details::op_data_t.
48 
49 template< typename Operation_Data >
51 
52 template< typename Operation_Data >
54 
55 namespace details
56 {
57 
58 /*!
59  * \brief A main class for implementation of time-unlimited
60  * asynchronous one-time operation.
61  *
62  * This class contains an information about completion handlers for
63  * async operation.
64  *
65  * Do not create objects of this class directly (unless you really know
66  * what you are doing).
67  * Use so_5::extra::async_op::time_unlimited::make() helper function for that.
68  *
69  * \note
70  * Instances of that class should be created only as dynamically allocated
71  * objects. It is because smart pointers are created inside the instance
72  * (for example completed_on() creates intrusive_ptr_t for `this`). Because
73  * of that this class has a protected destructor.
74  *
75  * \attention
76  * This is not a thread-safe type. It is beter and safer to work with
77  * an object of that type inside an agent for which that object is created.
78  *
79  * \since
80  * v.1.0.4
81  */
82 class op_data_t : protected ::so_5::atomic_refcounted_t
83  {
84  friend class ::so_5::intrusive_ptr_t<op_data_t>;
85 
86  template< typename Operation_Data >
88  template< typename Operation_Data >
90 
91  private :
92  //! Description of one subscription.
94  {
95  //! Mbox from that a message is expected.
97 
98  //! State for that a subscription should be created.
99  /*!
100  * \attention
101  * Can't be nullptr.
102  */
103  const ::so_5::state_t * m_state;
104 
105  //! Subscription type.
106  /*!
107  * \note
108  * This is a subscription type. Not a type which will
109  * be passed to the event handler.
110  */
112 
113  //! Event handler.
115 
116  //! Initializing constructor.
118  so_5::mbox_t mbox,
119  const so_5::state_t & state,
120  std::type_index subscription_type,
121  so_5::event_handler_method_t handler )
122  : m_mbox( std::move(mbox) )
123  , m_state( &state )
125  , m_handler( std::move(handler) )
126  {}
127  };
128 
129  //! Owner of async operation.
131 
132  //! The status of the async operation.
134 
135  //! Subscriptions which should be created on activation.
137 
138  protected :
139  // NOTE: constructor and destructor will be available only
140  // for friends and for derived classes.
141 
142  //! Initializing constructor.
144  //! An agent which owns async operation.
145  ::so_5::outliving_reference_t<::so_5::agent_t> owner )
146  : m_owner(owner)
147  {}
148 
149  ~op_data_t() noexcept
150  {}
151 
152  //! Reserve a capacity for vector with subscriptions' data.
153  void
154  reserve( std::size_t capacity )
155  {
156  m_subscriptions.reserve( capacity );
157  }
158 
159  //! Add an operation completion handler.
160  /*!
161  * This method stores description of a competion handler. This
162  * description will be used later in activate() method for subscription
163  * to a completion message/signal.
164  *
165  * \tparam Operation_Data An actual type of operation data object.
166  * In the most cases it will be op_data_t itself. But for debugging or
167  * testing purposes it can also be a derived class. This type is
168  * necessary to store the right smart pointer to actual operation
169  * data object in event handler wrapper.
170  *
171  * \tparam Msg_Target A type of destination for message/signal about
172  * the completion of the async operation.
173  * It can be a const reference to so_5::mbox_t, so_5::agent_t,
174  * so_5::adhoc_agent_definition_proxy_t.
175  *
176  * \tparam Event_Handler A type of handler for message/signal about
177  * the completion of the async operation.
178  */
179  template<
180  typename Operation_Data,
181  typename Msg_Target,
182  typename Event_Handler >
183  void
185  //! A smart pointer to the actual instance of operation data.
186  ::so_5::intrusive_ptr_t< Operation_Data > actual_data,
187  //! A destination for message about operation completion.
188  Msg_Target && msg_target,
189  //! A state in which message should be handled.
190  const ::so_5::state_t & state,
191  //! A message handler.
192  Event_Handler && evt_handler )
193  {
195 
196  const auto mbox = ::so_5::extra::async_op::details::target_to_mbox(
197  msg_target );
198 
199  auto evt_handler_info =
201  mbox,
202  m_owner.get(),
204 
206  [self = std::move(actual_data),
208  ::so_5::message_ref_t & msg )
209  {
210  self->completed();
211  user_handler( msg );
212  };
213 
215  mbox,
216  state,
218  std::move(actual_handler) );
219  }
220 
221  /*!
222  * \brief Performs all necessary activation actions.
223  *
224  * \note
225  * It throws if:
226  * - the operation is already activated;
227  * - there is no defined completion handlers.
228  */
229  void
231  {
232  ensure_not_activated();
233 
234  if( !m_subscriptions.empty() )
235  {
236  create_subscriptions();
238  }
239  else
240  SO_5_THROW_EXCEPTION(
241  ::so_5::extra::async_op::errors::rc_no_completion_handler,
242  "Operation can't be activated without any completion "
243  "handler" );
244  }
245 
246  //! Cancel async operation.
247  /*!
248  * If an async operation is in progress then all subscriptions
249  * will be destroyed and all information about completion handlers
250  * will be erased.
251  *
252  * \note
253  * It is safe to cancel an operation which wasn't activacted or
254  * was already finished.
255  * If cancel() is called before activate() then all information
256  * about completion handlers created by previous calls to
257  * add_completion_handler() will be lost.
258  *
259  * \attention
260  * This method is marked as noexcept because event unsubscription
261  * operations shouldn't throw. But if such operation throws then
262  * there is no way to recover.
263  */
264  void
265  cancel() noexcept
266  {
268  {
269  destroy_and_clear_subscriptions();
271  }
272  else if( status_t::not_activated == m_status )
273  {
274  m_subscriptions.clear();
275  }
276  }
277 
278  //! Get the current status of the operation.
279  SO_5_NODISCARD status_t
280  current_status() const noexcept
281  {
282  return m_status;
283  }
284 
285  //! Is there any completion handler?
286  SO_5_NODISCARD bool
287  has_completion_handlers() const noexcept
288  {
289  return !m_subscriptions.empty();
290  }
291 
292  private :
293  //! Check if operation is activated and throw an exception if it is.
294  void
296  {
297  if( status_t::activated == m_status )
300  "Operation can't be performed when async_op is already "
301  "activated" );
302  }
303 
304  //! Perform operation completion procedure.
305  /*!
306  * All subscriptions will be destroyed. All information about
307  * subscriptions will be deleted.
308  *
309  * Status will be changed to status_t::completed.
310  */
311  void
312  completed() noexcept
313  {
316  }
317 
318  //! Subscribe agent for all subscriptions in the subscriptions' container.
319  /*!
320  * \note
321  * If an exception is thrown during subscription then all previously
322  * created subscriptions will be destroyed.
323  */
324  void
326  {
327  // All subscriptions must be destroyed if an exception
328  // is thrown.
329  std::size_t current_index = 0;
330  try
331  {
333  {
334  auto & sd = m_subscriptions[ current_index ];
336  sd.m_mbox,
338  *(sd.m_state),
339  sd.m_handler,
341  }
342  }
343  catch(...)
344  {
345  // All created subscriptions should be dropped.
347 
348  throw;
349  }
350  }
351 
352  //! Destroy all subscriptions and clean subscriptions' container.
353  void
355  {
358  }
359 
360  //! Destroy subscriptions in range [0..n).
361  void
363  //! Last index of subscription in m_subscriptions container
364  //! which shouldn't be included.
365  const std::size_t n ) noexcept
366  {
367  for( std::size_t i = 0; i != n; ++i )
368  {
369  const auto & sd = m_subscriptions[ i ];
371  sd.m_mbox,
373  *(sd.m_state) );
374  }
375  }
376  };
377 
378 //
379 // op_shptr_t
380 //
381 /*!
382  * \brief An alias for smart pointer to operation data.
383  *
384  * \since
385  * v.1.0.4
386  */
387 template< typename Operation_Data >
389 
390 } /* namespace details */
391 
392 /*!
393  * \brief An object that allows to cancel async operation.
394  *
395  * Usage example:
396  * \code
397  * namespace asyncop = so_5::extra::async_op::time_unlimited;
398  * class demo : public so_5::agent_t {
399  * asyncop::cancellation_point_t<> cp_;
400  * ...
401  * void initiate_async_op() {
402  * auto op = asyncop::make<timeout>(*this);
403  * op.completed_on(...);
404  * cp_ = op.activate(...);
405  * }
406  * void on_interruption_signal(mhood_t<interrupt_activity> cmd) {
407  * // Operation should be cancelled.
408  * cp_.cancel();
409  * ...
410  * }
411  * };
412  * \endcode
413  *
414  * \note
415  * This class is DefaultConstructible and Moveable, but not Copyable
416  * and not CopyConstructible.
417  *
418  * \attention
419  * Objects of this class are not thread safe. It means that cancellation
420  * point should be used only by agent which created it. And the cancellation
421  * point can't be used inside thread-safe event handlers of that agent.
422  *
423  * \tparam Operation_Data Type of actual operation data representation.
424  * Please note that this template parameter is indended to be used for
425  * debugging and testing purposes only.
426  *
427  * \since
428  * v.1.0.4
429  */
430 template< typename Operation_Data = details::op_data_t >
432  {
433  private :
434  template<typename Op_Data> friend class definition_point_t;
435 
436  //! Actual data for async op.
437  /*!
438  * \note
439  * This can be a nullptr if the default constructor was used,
440  * or if operation is already cancelled, or if the content of
441  * the cancellation_point was moved to another object.
442  */
444 
445  //! Initializing constructor to be used by definition_point.
447  //! Actual data for async operation.
448  //! Can't be null.
449  details::op_shptr_t< Operation_Data > op )
450  : m_op( std::move(op) )
451  {}
452 
453  public :
454  cancellation_point_t() = default;
455 
456  cancellation_point_t( const cancellation_point_t & ) = delete;
458 
460  operator=( const cancellation_point_t & ) = delete;
461 
463  operator=( cancellation_point_t && ) = default;
464 
465  //! Get the status of the operation.
466  /*!
467  * \note
468  * The value status_t::unknown_moved_away can be returned if
469  * the actual data of the async operation was moved to another object
470  * (like another cancellation_point_t). Or after a call to
471  * cleanup() method.
472  */
473  SO_5_NODISCARD status_t
474  status() const noexcept
475  {
476  if( m_op)
477  return m_op->current_status();
479  }
480 
481  //! Can the async operation be cancelled via this cancellation point?
482  /*!
483  * \return true if the cancellation_point holds actual async operation's
484  * data and this async operation is not completed yet.
485  */
486  SO_5_NODISCARD bool
487  is_cancellable() const noexcept
488  {
489  return m_op && status_t::activated == m_op->current_status();
490  }
491 
492  //! An attempt to cancel the async operation.
493  /*!
494  * \note
495  * Operation will be cancelled only if (true == is_cancellable()).
496  *
497  * It is safe to call cancel() if the operation is already
498  * cancelled or completed. In that case the call to
499  * cancel() will have no effect.
500  */
501  void
502  cancel() noexcept
503  {
504  if( is_cancellable() )
505  {
506  m_op->cancel();
507  }
508  }
509 
510  //! Throw out a reference to the async operation data.
511  /*!
512  * A cancellation_point holds a reference to the async operation
513  * data. It means that the async operation data will be destroyed
514  * only when the cancellation_point will be destroyed. For example,
515  * in that case:
516  * \code
517  * namespace asyncop = so_5::extra::async_op::time_unlimited;
518  * class demo : public so_5::agent_t {
519  * ...
520  * asyncop::cancellation_point_t<> cp_;
521  * ...
522  * void initiate_async_op() {
523  * cp_ = asyncop::make<timeout_msg>(*this)
524  * ...
525  * .activate(...);
526  * ...
527  * }
528  * ...
529  * void on_some_interruption() {
530  * // Cancel asyncop.
531  * cp_.cancel();
532  * // Async operation is cancelled, but the async operation
533  * // data is still in memory. The data will be deallocated
534  * // only when cp_ receives new value or when cp_ will be
535  * // destroyed (e.g. after destruction of demo agent).
536  * }
537  * \endcode
538  *
539  * A call to cleanup() method removes the reference to the async
540  * operation data. It means that if the operation is already
541  * completed or cancelled, then the operation data
542  * fill be deallocated.
543  *
544  * \note
545  * If the operation is still in progress then a call to cleanup()
546  * doesn't break the operation. You need to call cancel() manually
547  * before calling cleanup() to cancel the operation.
548  */
549  void
550  cleanup() noexcept
551  {
552  m_op.reset();
553  }
554  };
555 
556 /*!
557  * \brief An interface for definition of async operation.
558  *
559  * Object of this type is usually created by make() function and
560  * is used for definition of async operation. Completion and timeout
561  * handlers are set for async operation by using definition_point object.
562  *
563  * Then an user calls activate() method and the definition_point transfers
564  * the async operation data into cancellation_point object. It means that
565  * after a call to activate() method the definition_point object should
566  * not be used. Because it doesn't hold any async operation anymore.
567  *
568  * A simple usage without storing the cancellation_point:
569  * \code
570  * namespace asyncop = so_5::extra::async_op::time_unlimited;
571  * class demo : public so_5::agent_t {
572  * ...
573  * void initiate_async_op() {
574  * // Create a definition_point for a new async operation...
575  * asyncop::make(*this)
576  * // ...then set up completion handler(s)...
577  * .completed_on(
578  * *this,
579  * so_default_state(),
580  * &demo::on_first_completion_msg )
581  * .completed_on(
582  * some_external_mbox_,
583  * some_user_defined_state_,
584  * [this](mhood_t<another_completion_msg> cmd) {...})
585  * // ...and now we can activate the operation.
586  * .activate();
587  * ...
588  * }
589  * };
590  * \endcode
591  * \note
592  * There is no need to hold definition_point object after activation
593  * of the async operation. This object can be safely discarded.
594  *
595  * A more complex example using cancellation_point for
596  * cancelling the operation.
597  * \code
598  * namespace asyncop = so_5::extra::async_op::time_unlimited;
599  * class demo : public so_5::agent_t {
600  * ...
601  * // Cancellation point for the async operation.
602  * asyncop::cancellation_point_t<> cp_;
603  * ...
604  * void initiate_async_op() {
605  * // Create a definition_point for a new async operation
606  * // and store the cancellation point after activation.
607  * cp_ = asyncop::make(*this)
608  * // ...then set up completion handler(s)...
609  * .completed_on(
610  * *this,
611  * so_default_state(),
612  * &demo::on_first_completion_msg )
613  * .completed_on(
614  * some_external_mbox_,
615  * some_user_defined_state_,
616  * [this](mhood_t<another_completion_msg> cmd) {...})
617  * // ...and now we can activate the operation.
618  * .activate();
619  * ...
620  * }
621  * ...
622  * void on_abortion_signal(mhood_t<abort_signal>) {
623  * // The current async operation should be cancelled.
624  * cp_.cancel();
625  * }
626  * };
627  * \endcode
628  *
629  * \note
630  * There are two forms of activate() method. The first one doesn't receive
631  * any arguments. It was shown in the examples above. The second one receives
632  * the lambda-function as argument. It can be used when some addtional
633  * actions should be performed during the activation of the async operation.
634  * For example:
635  * \code
636  * void initiate_async_op() {
637  * asyncop::make(*this)
638  * .completed_on(...)
639  * .completed_on(...)
640  * .activate([this] {
641  * // Several messages must be sent at the start of async op.
642  * so_5::send<first_initial_msg>(some_target, ...);
643  * so_5::send<second_initial_msg>(some_target, ...);
644  * ...
645  * });
646  * }
647  * \endcode
648  *
649  * \note
650  * This class is Moveable, but not DefaultConstructible nor Copyable.
651  *
652  * \attention
653  * Objects of this class are not thread safe. It means that a definition
654  * point should be used only by agent which created it. And the definition
655  * point can't be used inside thread-safe event handlers of that agent.
656  *
657  * \since
658  * v.1.0.4
659  */
660 template<
661  typename Operation_Data = details::op_data_t >
662 class definition_point_t
663  {
664  //! Actual operation data.
665  /*!
666  * \note
667  * This pointer can be nullptr after activation or after the
668  * content of the object is moved away.
669  */
671 
672  //! Checks that the definition_point owns async operation data.
673  void
675  {
676  if( !m_op )
679  "an attempt to use empty definition_point object" );
680  }
681 
682  public :
683  //! Initializing constructor.
685  //! The owner of the async operation.
686  ::so_5::outliving_reference_t< ::so_5::agent_t > owner )
687  : m_op( new Operation_Data( owner ) )
688  {}
689 
691  {
692  // If operation data is still here then it means that
693  // there wasn't call to `activate()` and we should cancel
694  // all described handlers.
695  // This will lead to deallocation of operation data.
696  if( this->m_op )
697  this->m_op->cancel();
698  }
699 
700  definition_point_t( const definition_point_t & ) = delete;
702  operator=( const definition_point_t & ) = delete;
703 
704  definition_point_t( definition_point_t && ) = default;
706  operator=( definition_point_t && ) = default;
707 
708  /*!
709  * \brief Reserve a space for storage of completion handlers.
710  *
711  * Usage example:
712  * \code
713  * namespace asyncop = so_5::extra::async_op::time_unlimited;
714  * auto op = asyncop::make(some_agent);
715  * // Reserve space for four completion handlers.
716  * op.reserve_completion_handlers_capacity(4);
717  * op.completed_on(...);
718  * op.completed_on(...);
719  * op.completed_on(...);
720  * op.completed_on(...);
721  * op.activate();
722  * \endcode
723  */
726  //! A required capacity.
727  std::size_t capacity ) &
728  {
730 
731  m_op->reserve( capacity );
732 
733  return *this;
734  }
735 
736  //! Just a proxy for actual version of %reserve_completion_handlers_capacity.
737  template< typename... Args >
738  auto
740  {
741  return std::move(this->reserve_completion_handlers_capacity(
742  std::forward<Args>(args)... ));
743  }
744 
745  /*!
746  * \brief Checks if the async operation can be activated.
747  *
748  * The operation can be activated if the definition_point still
749  * holds the operation data (e.g. operation is not activated yet) and
750  * there is at least one completion handler for the operation.
751  */
752  SO_5_NODISCARD bool
753  is_activable() const noexcept
754  {
755  // Operation is activable if we still hold the operation data.
756  return m_op && m_op->has_completion_handlers();
757  }
758 
759  /*!
760  * \brief Add a completion handler for the async operation.
761  *
762  * Usage example:
763  * \code
764  * namespace asyncop = so_5::extra::async_op::time_unlimited;
765  * class demo : public so_5::agent_t {
766  * ...
767  * void initiate_async_op() {
768  * asyncop::make<timeout>(*this)
769  * .completed_on(
770  * *this,
771  * so_default_state(),
772  * &demo::some_event )
773  * .completed_on(
774  * some_mbox_,
775  * some_agent_state_,
776  * [this](mhood_t<some_msg> cmd) {...})
777  * ...
778  * .activate(...);
779  * }
780  * };
781  * \endcode
782  *
783  * \note
784  * The completion handler will be stored inside async operation
785  * data. Actual subscription for it will be made during activation
786  * of the async operation.
787  *
788  * \tparam Msg_Target It can be a mbox, or a reference to an agent.
789  * In the case if Msg_Target if a reference to an agent the agent's
790  * direct mbox will be used as message source.
791  *
792  * \tparam Event_Handler Type of actual handler for message/signal.
793  * It can be a pointer to agent's method or lambda (or another
794  * type of functional object).
795  */
796  template<
797  typename Msg_Target,
798  typename Event_Handler >
801  //! A source from which a completion message is expected.
802  //! It \a msg_target is a reference to an agent then
803  //! the agent's direct mbox will be used.
805  //! A state for which that completion handler will be subscribed.
806  const ::so_5::state_t & state,
807  //! The completion handler itself.
809  {
811 
813  this->m_op,
815  state,
817 
818  return *this;
819  }
820 
821  //! Just a proxy for the main version of %completed_on.
822  template< typename... Args >
824  completed_on( Args && ...args ) &&
825  {
826  return std::move(this->completed_on(std::forward<Args>(args)...));
827  }
828 
829  //! Activate async operation with addition starting action.
830  /*!
831  * This method performs two steps:
832  *
833  * 1. Activates the async operation.
834  * 2. Calls \a action lambda-function (or functional object).
835  *
836  * It an exception is thrown from \a action then the activated
837  * async operation will be cancelled automatically.
838  *
839  * Usage example:
840  * \code
841  * namespace asyncop = so_5::extra::async_op::time_unlimited;
842  * class demo : public so_5::agent_t {
843  * public:
844  * ...
845  * virtual void so_evt_start() override {
846  * // Set up operation completion handlers...
847  * asyncop::make(*this)
848  * .completed_on(...)
849  * .completed_on(...)
850  * .completed_on(...)
851  * // And now the operation can be activated.
852  * .activate([this] {
853  * ... // Some initial actions like sending a message...
854  * });
855  * ...
856  * }
857  * };
858  * \endcode
859  *
860  * \attention
861  * It throws if `!is_activable()`.
862  *
863  * \attention
864  * If an exception is thrown during the activation procedure then
865  * the definition_point will become empty. It means that after an
866  * exception from activate() the definition_point object should not
867  * be used.
868  *
869  * \tparam Activation_Action A type of lambda-function or functional
870  * object to be excecuted on activation of operation.
871  */
872  template< typename Activation_Action >
875  //! A lambda-function or functional object which will be called
876  //! after creation of all necessary subscriptions and switching
877  //! to activated status.
879  {
880  if( !this->is_activable() )
883  "definition_point_t doesn't hold operation data anymore." );
884  auto op = std::move(m_op);
885 
886  op->activate();
887 
889  [&] { action(); },
890  [&] { op->cancel(); } );
891 
892  return { std::move(op) };
893  }
894 
895  //! Activate async operation.
896  /*!
897  * Usage example:
898  * \code
899  * namespace asyncop = so_5::extra::async_op::time_unlimited;
900  * class demo : public so_5::agent_t {
901  * public:
902  * ...
903  * virtual void so_evt_start() override {
904  * // Create an async operation...
905  * asyncop::make(*this)
906  * // Then set up completion handlers...
907  * ->completed_on(...)
908  * .completed_on(...)
909  * .completed_on(...)
910  * // And now the operation can be activated.
911  * .activate();
912  * ...
913  * }
914  * };
915  * \endcode
916  *
917  * \attention
918  * It throws if `!is_activable()`.
919  *
920  * \attention
921  * If an exception is thrown during the activation procedure then
922  * the definition_point will become empty. It means that after an
923  * exception from activate() the definition_point object should not
924  * be used.
925  */
928  {
929  return this->activate( []{/* Nothing to do*/} );
930  }
931 
932  //! Just a proxy for actual %activate() methods.
933  template< typename... Args >
934  auto
935  activate( Args && ...args ) &&
936  {
937  return this->activate( std::forward<Args>(args)... );
938  }
939  };
940 
941 //
942 // make
943 //
944 /*!
945  * \brief Helper function for creation an instance of async operation.
946  *
947  * Instead of creation of op_data_t's instances directly by hand this
948  * factory function should be used:
949  * \code
950  * namespace asyncop = so_5::extra::async_op::time_unlimited;
951  * class demo : public so_5::agent_t {
952  * public:
953  * ...
954  * virtual void so_evt_start() override {
955  * // Create an async operation...
956  * asyncop::make(*this)
957  * // ...set up operation completion handlers...
958  * .completed_on(...)
959  * .completed_on(...)
960  * .completed_on(...)
961  * // And now the operation can be activated.
962  * .activate();
963  * ...
964  * }
965  * };
966  * \endcode
967  *
968  * \since
969  * v.1.0.4
970  */
973  //! Agent for that this async operation will be created.
974  ::so_5::agent_t & owner )
975  {
976  return { ::so_5::outliving_mutable(owner) };
977  }
978 
979 } /* namespace time_unlimited */
980 
981 } /* namespace async_op */
982 
983 } /* namespace extra */
984 
985 } /* namespace so_5 */
auto activate(Args &&...args) &&
Just a proxy for actual activate() methods.
void add_completion_handler(::so_5::intrusive_ptr_t< Operation_Data > actual_data, Msg_Target &&msg_target, const ::so_5::state_t &state, Event_Handler &&evt_handler)
Add an operation completion handler.
details::op_shptr_t< Operation_Data > m_op
Actual operation data.
Status of operation is unknown because the operation data has been moved to another proxy-object...
Ranges for error codes of each submodules.
Definition: details.hpp:13
details::op_shptr_t< Operation_Data > m_op
Actual data for async op.
definition_point_t & operator=(definition_point_t &&)=default
cancellation_point_t & operator=(const cancellation_point_t &)=delete
definition_point_t & operator=(const definition_point_t &)=delete
SO_5_NODISCARD definition_point_t< details::op_data_t > make(::so_5::agent_t &owner)
Helper function for creation an instance of async operation.
definition_point_t(::so_5::outliving_reference_t< ::so_5::agent_t > owner)
Initializing constructor.
::so_5::outliving_reference_t<::so_5::agent_t > m_owner
Owner of async operation.
definition_point_t & reserve_completion_handlers_capacity(std::size_t capacity) &
Reserve a space for storage of completion handlers.
void cleanup() noexcept
Throw out a reference to the async operation data.
cancellation_point_t & operator=(cancellation_point_t &&)=default
void ensure_not_empty() const
Checks that the definition_point owns async operation data.
void activate()
Performs all necessary activation actions.
status_t m_status
The status of the async operation.
definition_point_t(const definition_point_t &)=delete
void cancel() noexcept
Cancel async operation.
cancellation_point_t(details::op_shptr_t< Operation_Data > op)
Initializing constructor to be used by definition_point.
void destroy_subscriptions_up_to(const std::size_t n) noexcept
Destroy subscriptions in range [0..n).
const ::so_5::state_t * m_state
State for that a subscription should be created.
auto reserve_completion_handlers_capacity(Args &&...args) &&
Just a proxy for actual version of reserve_completion_handlers_capacity.
subscription_data_t(so_5::mbox_t mbox, const so_5::state_t &state, std::type_index subscription_type, so_5::event_handler_method_t handler)
Initializing constructor.
void reserve(std::size_t capacity)
Reserve a capacity for vector with subscriptions&#39; data.
std::vector< subscription_data_t > m_subscriptions
Subscriptions which should be created on activation.
op_data_t(::so_5::outliving_reference_t<::so_5::agent_t > owner)
Initializing constructor.
cancellation_point_t(const cancellation_point_t &)=delete
status_t
Enumeration for status of operation.