RTI Connext Modern C++ API
Version 6.1.1
|
<<extension>> Dispatches dds::core::cond::Condition objects using separate threads of execution. Unlike a normal dds::core::cond::WaitSet, which operates on the current thread, an AsyncWaitSet uses a thread pool. More...
#include <rti/core/cond/AsyncWaitSet.hpp>
<<extension>> Dispatches dds::core::cond::Condition objects using separate threads of execution. Unlike a normal dds::core::cond::WaitSet, which operates on the current thread, an AsyncWaitSet uses a thread pool.
rti::core::cond::AsyncWaitSet provides a proactive model to process application events through dds::core::cond::Condition objects. rti::core::cond::AsyncWaitSet owns a pool of threads to asynchronously wait for the attached dds::core::cond::Condition objects to trigger and dispatch them upon wakeup. The asynchronous behavior is the main key different with regards to the dds::core::cond::WaitSet.
The class diagram and its collaborators is shown below:
rti::core::cond::AsyncWaitSet internally applies a leader-follower pattern for the orchestration of the thread pool. Once a rti::core::cond::AsyncWaitSet starts, it will create the thread pool of M
threads from which only one thread will become the Leader
thread, and remaining threads will become the Followers
, where:
Leader
thread is the one waiting for the attached dds::core::cond::Condition to trigger. Remaining threads in the pool, if any, are either idle awaiting to become the leader or busy while processing active dds::core::cond::Condition. Leader
thread resigns its leader status to become a Processor
thread and dispatch the next active dds::core::cond::Condition through the dds::core::cond::Condition::dispatch operation. Follower
threads wakes up and becomes the new leader to resume the wait for dds::core::cond::Condition. This behavior implies the following considerations:
M
threads, only one is the leader, P
are processing active dds::core::cond::Condition, and F
are idle followers. rti::core::cond::AsyncWaitSet has a built-in dispatcher that guarantees fairness and avoids starvation of dds::core::cond::Condition objects. By applying a round-robin distribution policy, each attached and active dds::core::cond::Condition is dispatched within a finite period of time, assuming the functor handler always return control after the dds::core::cond::Condition::dispatch operation.
A key aspect of the rti::core::cond::AsyncWaitSet is the thread safety. rti::core::cond::AsyncWaitSet interface is thread safe, so you can concurrently call any operation on the rti::core::cond::AsyncWaitSet object from multiple threads in your application.
Furthermore, rti::core::cond::AsyncWaitSet also safely interacts with its own thread pool. Internally, the rti::core::cond::AsyncWaitSet applies the asynchronous completion token pattern to perform activities that involve synchronization with the thread pool.
For instance to detach a dds::core::cond::Condition, the rti::core::cond::AsyncWaitSet generates an internal request to its thread pool to process it. As soon as the detachment completes, the thread pool provides the notification through an associated completion token.
For a finer control on this behavior, each rti::core::cond::AsyncWaitSet operation where this applies comes in two flavors:
Default:
the operation hides all the details of the completion token and returns after the operation completes. Operations of this kind internally use an implicit rti::core::cond::AsyncWaitSetCompletionToken. The rti::core::cond::AsyncWaitSet creates and reuses rti::core::cond::AsyncWaitSetCompletionToken objects as needed. This is the recommended flavor unless your application has special resource needs. With
completion
token:
An overloaded version of the default one that also receives an rti::core::cond::AsyncWaitSetCompletionToken object on which you can wait on at any time for the actual operation to complete. This flavor is available to assist applications with resource constraints and that want more control on the interaction with the thread pool of the rti::core::cond::AsyncWaitSet. rti::core::cond::AsyncWaitSet incorporates a safety mechanism that prevents calling dds::core::cond::Condition::dispatch concurrently. rti::core::cond::AsyncWaitSet locks the dds::core::cond::Condition while a processor thread is dispatching it so no other thread within the pool can dispatch it again.
This mechanism ensures not only unexpected concurrent dispatch of a dds::core::cond::Condition but also spurious thread activity. Because it is responsibility of your application to reset the Condition trigger, there is a period of time in which the dispatched condition may remain active, causing the rti::core::cond::AsyncWaitSet to enter in a continous immediate wakeup from the wait. This behavior typically leads to thread hogging and high CPU usage.
Nevertheless, your application may still want to receive concurrent and controlled dispatch notifications. rti::core::cond::AsyncWaitSet will still allows you to unlock a dds::core::cond::Condition so any other available thread can dispatch the same condition concurrently while preventing the above mentioned problems. You can achive this by calling rti::core::cond::AsyncWaitSet::unlock_condition on the Condition being dispatched within the dispatch callback. Note that the AsyncWaitSet locks a Condition each time it dispatches it. Hence you need to unlock the Condition each time you want to enable a concurrent dispatch.
Besides dds::core::cond::Condition processing, you can listen to other kind of internal events related to the rti::core::cond::AsyncWaitSet and its thread pool by means of the rti::core::cond::AsyncWaitSetListener.
rti::core::cond::AsyncWaitSet exposes operations to start and stop the asynchronous wait, which involves the creation and deletion of the thread pool respectively.
rti::core::cond::AsyncWaitSet relies on thread-specific storage to provide the described functionality. Each application thread that calls an operation on a rti::core::cond::AsyncWaitSet will generate resources that will be associated with such thread. You can free these resources upon thread termination by calling DomainParticipantFactory::unregister_thread.
|
inline |
Constructor without arguments that create an rti::core::cond::AsyncWaitSet with default property.
|
inline |
Single-argument constructor that allows creating a a rti::core::cond::AsyncWaitSet with custom behavior.
You can provide rti::core::cond::AsyncWaitSetProperty::AsyncWaitSetProperty() as property
to create an rti::core::cond::AsyncWaitSet with default behavior.
The rti::core::cond::AsyncWaitSet is created with no listener installed.
the_property | <<in>> configuration rti::core::cond::AsyncWaitSetProperty |
|
inline |
Constructor that allows specifying a rti::core::cond::AsyncWaitSetListener.
Creates a new rti::core::cond::AsyncWaitSet with the specified property rti::core::cond::AsyncWaitSetProperty and rti::core::cond::AsyncWaitSetListener.
the_property | <<in>> configuration rti::core::cond::AsyncWaitSetProperty |
listener | <<in>> the rti::core::cond::AsyncWaitSetListener. Cannot be NULL. |
|
inline |
Initiates the asynchronous wait on this rti::core::cond::AsyncWaitSet.
This operation blocks until the start request completes. Upon successful return, it is guaranteed that this rti::core::cond::AsyncWaitSet has initiated the asynchronous wait and dispatch.
One | of the Standard Exceptions |
|
inline |
Initiates the asynchronous wait on this rti::core::cond::AsyncWaitSet.
If this operation succeeds, a start request has been scheduled and your application can use the provided completion_token
to wait for this rti::core::cond::AsyncWaitSet to process the request. If the rti::core::cond::AsyncWaitSetCompletionToken::wait operation returns successfully, it is guranteed that the thread pool has been created and the leader thread is waiting for the attached dds::core::cond::Condition to trigger.
Once this rti::core::cond::AsyncWaitSet is started, attached dds::core::cond::Condition will be dispatched through the dds::core::cond::Condition::dispatch operation when they trigger.
The start procedure causes the rti::core::cond::AsyncWaitSet to spawn all the threads within the thread pool, which involves the underlying operating system to allocate the associated thread stack and context for each thread. If a rti::core::cond::AsyncWaitSetListener is installed, this rti::core::cond::AsyncWaitSet will sequentially invoke the rti::core::cond::AsyncWaitSetListener::on_thread_spawned once per spwaned thread.
A rti::core::cond::AsyncWaitSet can be restarted after a stop. If this rti::core::cond::AsyncWaitSet is already started, this operation will return immediately with success, and waiting on the completion_token
will also return immediately with success.
completion_token | <<inout>> a valid rti::core::cond::AsyncWaitSetCompletionToken instance that can be used by your application to wait for the start request to complete. You can provide the special sentinel rti::core::cond::AsyncWaitSetCompletionToken::Ignore(). |
One | of the Standard Exceptions |
|
inline |
Initiates the stop procedure on this rti::core::cond::AsyncWaitSet that will stop the asynchronous wait.
This operation will block until the stop request completes. Upon successful return, it is guaranteed that this rti::core::cond::AsyncWaitSet stopped the asynchronous wait and dispatch.
One | of the Standard Exceptions |
|
inline |
Initiates the stop procedure on this rti::core::cond::AsyncWaitSet that will stop the asynchronous wait.
If this operation succeeds, a stop request has been scheduled and your application can use the provided completion_token
to wait for this rti::core::cond::AsyncWaitSet to process the request. If the rti::core::cond::AsyncWaitSetCompletionToken::wait operation returns successfully, it is guranteed that the thread pool has been deleted and this rti::core::cond::AsyncWaitSet no longer process any of the attached dds::core::cond::Condition objects.
Once this rti::core::cond::AsyncWaitSet is stopped, the dds::core::cond::Condition::dispatch will no longer be called on any of the attached dds::core::cond::Condition, no matter what their trigger value is.
The stop procedure causes the rti::core::cond::AsyncWaitSet to delete all the threads within the thread pool, which involves the underlying operating system to release the associated thread stack and context of each thread. If a rti::core::cond::AsyncWaitSetListener is installed, this rti::core::cond::AsyncWaitSet will sequentially invoke the rti::core::cond::AsyncWaitSetListener::on_thread_deleted once per deleted thread.
If this rti::core::cond::AsyncWaitSet is already stopped, this operation will return immediately with success, and waiting on the completion_token
will also return immediately with success.
completion_token | <<inout>> a valid rti::core::cond::AsyncWaitSetCompletionToken instance that can be used by your application to wait for the stop request to complete. You can provide the special sentinel rti::core::cond::AsyncWaitSetCompletionToken::Ignore(). |
One | of the Standard Exceptions |
|
inline |
Attaches the specified dds::core::cond::Condition to this rti::core::cond::AsyncWaitSet.
This operation will block until the attach request completes. Upon successful return, it is guaranteed that the specified dds::core::cond::Condition is attached.
condition | <<in>> dds::core::cond::Condition to be attached. |
One | of the Standard Exceptions |
|
inline |
Attaches the specified dds::core::cond::Condition to this rti::core::cond::AsyncWaitSet.
If this operation succeeds, an attach request has been scheduled and your application can use the output parameter completion_token
to wait for this rti::core::cond::AsyncWaitSet to process the request. rti::core::cond::AsyncWaitSetCompletionToken::wait operation returns successfully, it is guaranteed that the dds::core::cond::Condition is attached to this rti::core::cond::AsyncWaitSet.
Once the dds::core::cond::Condition is attached, its trigger value may cause the leader thread of the rti::core::cond::AsyncWaitSet to wake up call the dds::core::cond::Condition::dispatch operation.
dds::core::cond::Condition may be attached at any time independently of the state of the rti::core::cond::AsyncWaitSet.
condition | <<in>> dds::core::cond::Condition to be attached. |
completion_token | <<inout>> a valid rti::core::cond::AsyncWaitSetCompletionToken instance that can be used by your application to wait for the attach request to complete. You can provide the special sentinel rti::core::cond::AsyncWaitSetCompletionToken::Ignore(). |
One | of the Standard Exceptions |
|
inline |
Deaches the specified dds::core::cond::Condition from this rti::core::cond::AsyncWaitSet.
This operation blocks until the detach request completes. Upon successful return, it is guaranteed that the specified dds::core::cond::Condition is detached.
condition | <<in>> dds::core::cond::Condition to be detached. |
One | of the Standard Exceptions |
|
inline |
Detaches the specified dds::core::cond::Condition from this rti::core::cond::AsyncWaitSet.
If this operation succeeds, a detach request has been scheduled and your application can use the provided completion_token
to wait for this rti::core::cond::AsyncWaitSet to process the request. If the rti::core::cond::AsyncWaitSetCompletionToken::wait operation returns successfully, it is guaranteed that the dds::core::cond::Condition is detached from this rti::core::cond::AsyncWaitSet.
Once the dds::core::cond::Condition is detached, it is guaranteed that the rti::core::cond::AsyncWaitSet will no longer process it so it is safe for your application to release any resources associated with the detached dds::core::cond::Condition.
dds::core::cond::Condition may be detached at any time independently of the state of the rti::core::cond::AsyncWaitSet.
condition | <<in>> dds::core::cond::Condition to be detached. |
completion_token | <<inout>> a valid rti::core::cond::AsyncWaitSetCompletionToken instance that can be used by your application to wait for the detach request to complete. You can provide the special sentinel rti::core::cond::AsyncWaitSetCompletionToken::Ignore(). |
One | of the Standard Exceptions |
|
inline |
Attaches the specified dds::core::cond::Condition to this rti::core::cond::AsyncWaitSet.
This operation will block until the attach request completes. Upon successful return, it is guaranteed that the specified dds::core::cond::Condition is attached.
condition | <<in>> dds::core::cond::Condition to be attached. |
One | of the Standard Exceptions |
|
inline |
Deaches the specified dds::core::cond::Condition from this rti::core::cond::AsyncWaitSet.
This operation blocks until the detach request completes. Upon successful return, it is guaranteed that the specified dds::core::cond::Condition is detached.
condition | <<in>> dds::core::cond::Condition to be detached. |
One | of the Standard Exceptions |
|
inline |
Allows the dds::core::cond::Condition under dispatch to be available for concurrent dispatch from another thread from the pool.
This operation can be called from the dispatch callback of the dds::core::cond::Condition this rti::core::cond::AsyncWaitSet is dispatching. After succesfully calling this operation, if the dds::core::cond::Condition becomes active this rti::core::cond::AsyncWaitSet is allowed to dispatch it again from any available thread from the pool.
You may call this operation any time you need the same dds::core::cond::Condition to be dispatched concurrently.
This operation will fail with dds::core::PreconditionNotMetError if you call it from a different context than the dispatch callback or on a different dds::core::cond::Condition.
One | of the Standard Exceptions |
|
inline |
Retrieves the rti::core::cond::AsyncWaitSetProperty configuration of the associated rti::core::cond::AsyncWaitSet.
One | of the Standard Exceptions |
|
inline |
Returns the list of attached dds::core::cond::Condition (s).
|
inline |
Retrieves the list of attached dds::core::cond::Condition (s).
attached_conditions | <<inout>> a ConditionSeq object where the list of attached conditions will be returned. |
One | of the Standard Exceptions |