RTI Connext Modern C++ API  Version 7.0.0

<<reference-type>> Allows an application to wait until one or more of the attached Condition objects have a trigger_value of true or else until the timeout expires. More...

#include <dds/core/cond/WaitSet.hpp>

Public Types

typedef std::vector< dds::core::cond::ConditionConditionSeq
 A vector of Conditions. More...
 

Public Member Functions

 WaitSet ()
 Creates a WaitSet with no conditions attached. More...
 
 WaitSetImpl (const rti::core::cond::WaitSetProperty &property)
 <<extension>> Creates a WaitSet with a WaitSetProperty More...
 
const ConditionSeq wait (const dds::core::Duration &timeout)
 Allows an application thread to wait for the occurrence of certain conditions. More...
 
const ConditionSeq wait ()
 Allows an application thread to wait for the occurrence of certain conditions. More...
 
ConditionSeqwait (ConditionSeq &triggered, const dds::core::Duration &timeout)
 Allows an application thread to wait for the occurrence of certain conditions. More...
 
ConditionSeqwait (ConditionSeq &triggered)
 Allows an application thread to wait for the occurrence of certain conditions. More...
 
void dispatch (const dds::core::Duration &timeout)
 Waits for at least one of the attached conditions to trigger and then dispatches the events. More...
 
void dispatch ()
 Waits for at least one of the attached conditions to trigger and then dispatches the events. More...
 
WaitSetoperator+= (dds::core::cond::Condition cond)
 Same as attach_condition() More...
 
WaitSetoperator-= (dds::core::cond::Condition cond)
 Same as detach_condition(). More...
 
WaitSetattach_condition (dds::core::cond::Condition cond)
 Attaches a Condition to the WaitSet. More...
 
bool detach_condition (dds::core::cond::Condition cond)
 Detaches a Condition from the WaitSet. More...
 
ConditionSeq conditions () const
 Retrieves the list of attached conditions. More...
 
ConditionSeqconditions (ConditionSeq &conds) const
 Retrieves the list of attached conditions. More...
 
void detach_all ()
 <<extension>> Detaches all the conditions. More...
 
rti::core::cond::WaitSetProperty property () const
 <<extension>> Gets the WaitSetProperty More...
 
void property (const rti::core::cond::WaitSetProperty &property)
 <<extension>> Sets the property to configure the WaitSet to return after one or more trigger events have occurred. More...
 

Detailed Description

<<reference-type>> Allows an application to wait until one or more of the attached Condition objects have a trigger_value of true or else until the timeout expires.

Note
A WaitSet provides all the functions of a <<reference-type>> except close() and retain().

Usage

dds::core::cond::Condition (s) (in conjunction with wait-sets) provide an alternative mechanism to allow the middleware to communicate communication status changes (including arrival of data) to the application.

DDSWaitSetConditions.png
dds::core::cond::WaitSet and dds::core::cond::Condition (s)

This mechanism is wait-based. Its general use pattern is as follows:

Usually the first step is done in an initialization phase, while the others are put in the application main loop.

As there is no extra information passed from the middleware to the application when a wait returns (only the list of triggered dds::core::cond::Condition objects), dds::core::cond::Condition objects are meant to embed all that is needed to react properly when enabled. In particular, dds::core::Entity-related conditions are related to exactly one dds::core::Entity and cannot be shared.

The blocking behavior of the dds::core::cond::WaitSet is illustrated below.

DDSWaitSetBlocking.png
dds::core::cond::WaitSet blocking behavior

The result of a dds::core::cond::WaitSet::wait operation depends on the state of the dds::core::cond::WaitSet, which in turn depends on whether at least one attached dds::core::cond::Condition has a trigger_value of true. If the wait operation is called on dds::core::cond::WaitSet with state BLOCKED, it will block the calling thread. If wait is called on a dds::core::cond::WaitSet with state UNBLOCKED, it will return immediately. In addition, when the dds::core::cond::WaitSet transitions from BLOCKED to UNBLOCKED it wakes up any threads that had called wait on it.

A key aspect of the Condition and WaitSet mechanism is the setting of the trigger_value of each dds::core::cond::Condition.

The dds::core::cond::WaitSet cannot be used after calling DomainParticipantFactory::finalize_instance.

Trigger State of a dds::core::cond::StatusCondition

The trigger_value of a dds::core::cond::StatusCondition is the boolean OR of the ChangedStatusFlag of all the communication statuses (see Status Kinds) to which it is sensitive. That is, trigger_value == false only if all the values of the ChangedStatusFlags are false.

The sensitivity of the dds::core::cond::StatusCondition to a particular communication status is controlled by the list of enabled_statuses set on the condition by means of the dds::core::cond::StatusCondition::enabled_statuses(const dds::core::status::StatusMask&) operation.

Once the trigger_value of a StatusCondition becomes true, it remains true until the status that changed is reset. To reset a status, call the related get_*_status() operation. Or, in the case of the data available status, call read(), take(), or one of their variants. Therefore, if you are using a dds::core::cond::StatusCondition on a dds::core::cond::WaitSet to be notified of events, your thread will wake up when one of the statuses associated with the StatusCondition becomes true. If you do not reset the status, the StatusCondition trigger_value remains true and your WaitSet will not block again; it will immediately wake up when you call dds::core::cond::WaitSet::wait.

Trigger State of a dds::sub::cond::ReadCondition

Similar to the dds::core::cond::StatusCondition, a dds::sub::cond::ReadCondition also has a trigger_value that determines whether the attached dds::core::cond::WaitSet is BLOCKED or UNBLOCKED. However, unlike the dds::core::cond::StatusCondition, the trigger_value of the dds::sub::cond::ReadCondition is tied to the presence of at least a sample managed by RTI Connext with dds::sub::status::SampleState and dds::sub::status::ViewState matching those of the dds::sub::cond::ReadCondition. Furthermore, for the dds::sub::cond::QueryCondition to have a trigger_value == true, the data associated with the sample must be such that the query_expression evaluates to true.

The fact that the trigger_value of a dds::sub::cond::ReadCondition depends on the presence of samples on the associated dds::sub::DataReader implies that a single take operation can potentially change the trigger_value of several dds::sub::cond::ReadCondition or dds::sub::cond::QueryCondition conditions. For example, if all samples are taken, any dds::sub::cond::ReadCondition and dds::sub::cond::QueryCondition conditions associated with the dds::sub::DataReader that had their trigger_value==TRUE before will see the trigger_value change to FALSE. Note that this does not guarantee that dds::core::cond::WaitSet objects that were separately attached to those conditions will not be woken up. Once we have trigger_value==TRUE on a condition, it may wake up the attached dds::core::cond::WaitSet, the condition transitioning to trigger_value==FALSE does not necessarily 'unwakeup' the WaitSet as 'unwakening' may not be possible in general.

The consequence is that an application blocked on a dds::core::cond::WaitSet may return from the wait with a list of conditions, some of which are not no longer 'active'. This is unavoidable if multiple threads are concurrently waiting on separate dds::core::cond::WaitSet objects and taking data associated with the same dds::sub::DataReader entity.

To elaborate further, consider the following example: A dds::sub::cond::ReadCondition that has a sample_state_mask = {dds::sub::status::SampleState::not_read()} will have trigger_value of true whenever a new sample arrives and will transition to false as soon as all the newly-arrived samples are either read (so their sample state changes to READ) or taken (so they are no longer managed by RTI Connext). However if the same dds::sub::cond::ReadCondition had a sample_state_mask = { dds::sub::status::SampleState::read(), dds::sub::status::SampleState::not_read() }, then the trigger_value would only become false once all the newly-arrived samples are taken (it is not sufficient to read them as that would only change the sample state to READ), which overlaps the mask on the dds::sub::cond::ReadCondition.

Trigger State of a dds::core::cond::GuardCondition

The trigger_value of a dds::core::cond::GuardCondition is completely controlled by the application via the operation dds::core::cond::GuardCondition::trigger_value().

See also
Status Kinds
dds::core::cond::StatusCondition, dds::core::cond::GuardCondition
Listener
See also
Waitset Use Cases
Examples:
Foo_subscriber.cxx.

Member Typedef Documentation

◆ ConditionSeq

typedef std::vector<dds::core::cond::Condition> dds::core::cond::WaitSet::ConditionSeq

A vector of Conditions.

Constructor & Destructor Documentation

◆ WaitSet()

dds::core::cond::WaitSet::WaitSet ( )
inline

Creates a WaitSet with no conditions attached.

Member Function Documentation

◆ WaitSetImpl()

dds::core::cond::WaitSet::WaitSetImpl ( const rti::core::cond::WaitSetProperty property)

<<extension>> Creates a WaitSet with a WaitSetProperty

◆ wait() [1/4]

const ConditionSeq dds::core::cond::WaitSet::wait ( const dds::core::Duration timeout)
inline

Allows an application thread to wait for the occurrence of certain conditions.

If none of the conditions attached to the dds::core::cond::WaitSet have a trigger_value of true, the wait operation will block, suspending the calling thread.

The result of the wait operation is the list of all the attached conditions that have a trigger_value of true (i.e., the conditions that unblocked the wait).

The wait operation takes a timeout argument that specifies the maximum duration for the wait. If this duration is exceeded and none of the attached dds::core::cond::Condition objects are true, wait will return an empty condition sequence.

Note: The resolution of the timeout period is constrained by the resolution of the system clock.

It is not allowable for more than one application thread to be waiting on the same WaitSet. If the wait operation is invoked on a WaitSet that already has a thread blocking on it, the operation will return immediately with the value dds::core::PreconditionNotMetError.

Parameters
timeoutThe maximum time to wait
Returns
A vector containing the active conditions or an empty vector if the operation times out.
Exceptions
dds::core::PreconditionNotMetErroror one of the other Standard Exceptions. Note however that this operation does not throw dds::core::TimeoutError.

◆ wait() [2/4]

const ConditionSeq dds::core::cond::WaitSet::wait ( )
inline

Allows an application thread to wait for the occurrence of certain conditions.

This function is equivalent to wait(dds::core::Duration::infinite()).

See also
wait(const dds::core::Duration&)

◆ wait() [3/4]

ConditionSeq& dds::core::cond::WaitSet::wait ( ConditionSeq triggered,
const dds::core::Duration timeout 
)
inline

Allows an application thread to wait for the occurrence of certain conditions.

This function is equivalent to wait(const dds::core::Duration&) but reuses an existing vector instead of returning a new one.

Parameters
triggeredA vector where the active conditions will be added. Any element already present in the vector will be removed. If the operation times out, this vector will be empty.
timeoutThe wait timeout
Returns
A reference to triggered for convenience.
See also
wait(const dds::core::Duration&)

◆ wait() [4/4]

ConditionSeq& dds::core::cond::WaitSet::wait ( ConditionSeq triggered)
inline

Allows an application thread to wait for the occurrence of certain conditions.

This application is equivalent to wait(triggered, dds::core::Duration::infinite());

See also
wait(ConditionSeq&, const dds::core::Duration&)

◆ dispatch() [1/2]

void dds::core::cond::WaitSet::dispatch ( const dds::core::Duration timeout)
inline

Waits for at least one of the attached conditions to trigger and then dispatches the events.

This is an alternative, simpler pattern to the use of wait(). Instead of receiving the list of active conditions, the application associates a handler (functor) to each conditions before attaching it to the WaitSet. Whenever this function wakes up it will call–in the current thread context–the handler of each triggered condition before returning.

Note that each condition can only have one handler, so if you want to attach it to multiple WaitSets you may need to use wait() instead of dispatch().

Parameters
timeoutThe maximum time to wait. If that time elapses dispatch() will return without having called any of the condition handlers.
MT Safety:
It is not thread-safe to reset or replace a condition's handler while dispatch() is running. It should be detached first. Detaching a condition from a WaitSet while dispatch() is running is safe even if the condition is active, but whether the condition handler will be executed or not is undefined.
See also
WaitSet wait and dispatch examples
Examples:
Foo_subscriber.cxx.

◆ dispatch() [2/2]

void dds::core::cond::WaitSet::dispatch ( )
inline

Waits for at least one of the attached conditions to trigger and then dispatches the events.

This function is equivalent to dispatch(dds::core::Duration::infinite());

See also
dispatch(const dds::core::Duration&)

◆ operator+=()

WaitSet& dds::core::cond::WaitSet::operator+= ( dds::core::cond::Condition  cond)
inline

◆ operator-=()

WaitSet& dds::core::cond::WaitSet::operator-= ( dds::core::cond::Condition  cond)
inline

◆ attach_condition()

WaitSet& dds::core::cond::WaitSet::attach_condition ( dds::core::cond::Condition  cond)
inline

Attaches a Condition to the WaitSet.

It is possible to attach a dds::core::cond::Condition on a dds::core::cond::WaitSet that is currently being waited upon (via the wait operation). In this case, if the dds::core::cond::Condition has a trigger_value of true, then attaching the condition will unblock the dds::core::cond::WaitSet.

Parameters
cond<<in>> Condition to be attached.
Exceptions
Oneof the Standard Exceptions, or dds::core::OutOfResourcesError.

◆ detach_condition()

bool dds::core::cond::WaitSet::detach_condition ( dds::core::cond::Condition  cond)
inline

Detaches a Condition from the WaitSet.

If the dds::core::cond::Condition was not attached to the dds::core::cond::WaitSet the operation will return dds::core::InvalidArgumentError.

Parameters
cond<<in>> Condition to be detached.
Exceptions
Oneof the Standard Exceptions, or dds::core::PreconditionNotMetError.

◆ conditions() [1/2]

ConditionSeq dds::core::cond::WaitSet::conditions ( ) const
inline

Retrieves the list of attached conditions.

Returns
the list of attached conditions.

◆ conditions() [2/2]

ConditionSeq& dds::core::cond::WaitSet::conditions ( ConditionSeq conds) const
inline

Retrieves the list of attached conditions.

Parameters
condsA vector where the conditions will be aded
Returns
A reference to conds.

◆ detach_all()

void detach_all ( )

<<extension>> Detaches all the conditions.

Note
This function is an extension, it must be called via this->extensions()

◆ property() [1/2]

<<extension>> Gets the WaitSetProperty

Note
This function is an extension, it must be called via this->extensions()

◆ property() [2/2]

void property ( const rti::core::cond::WaitSetProperty property)

<<extension>> Sets the property to configure the WaitSet to return after one or more trigger events have occurred.

Note
This function is an extension, it must be called via this->extensions()