目录
- 2.4 Listeners, Conditions, and Wait-sets
- 2.4.1 Communication Status
- 2.4.2 Changes in Status
- 2.4.2.1 Plain communication statuses
- 2.4.2.2 Read Communication Statuses
- 2.2.4.3 Access through Listeners
- 2.2.4.3.1 Listener Access to Plain Communication Status
- 2.2.4.3.2 Listener Access to Read Communication Status
- 2.2.4.4 Conditions and Wait-sets
- 2.2.4.4.1 Trigger State of the StatusCondition
- 2.2.4.5 Trigger State of the ReadCondition
- 2.2.4.5.1 Trigger State of the GuardCondition
- 2.2.4.6 Combination
- 学习资料链接
2.4 Listeners, Conditions, and Wait-sets
Listeners和Conditions(和wait set相关)是两种允许APP知道DCPS有change的机制。
2.4.1 Communication Status
Communication Status是和Entity关联的,下表列出了所有Entity会有的status:
以上的status可以被分为两类:
- Read communication statuses:和data数据有关的,比如DATA_ON_READERS和DATA_AVAILABLE
- Plain communication statuses:其他所有
Read communication statuses不会独立出现,也就是说,至少会有两个status会被同时改变,例如DATA_ON_READERS + DATA_AVAILABLE。这些改变(grouping)会被发给APP,如何操作取决于下面两种不同机制。
对于每一个Plain communication statuse来说,都会有相关的结构去控制相关的status的值。这些值与status的改变相关,也和这些status本身有关(例如,包含累积计数)。与下文解释的两种不同机制一起使用。
上图对应了不同的status里面包含的值及其数据类型。
2.4.2 Changes in Status
每个entity的communication status都关联一个StatusChangedFlag。
此flag指示自上次APP“read”该状态以来,该特定通信状态是否发生了更改
2.4.2.1 Plain communication statuses
对于Plain communication statuses,StatusChangedFlag默认为FALSE,只有当状态改变才会设置为TRUE,并且当每次APP调用get_<plain communication status>
接口时都会重置成FALSE。
每当调用关联的listener操作时,通信状态也被重置为FALSE,因为侦听器隐式访问作为参数传递给操作的状态。
此规则的一个例外是当关联的侦听器是’ nil ‘listener时。’ nil ‘时,线程认为是NOOP,并且’ nil '不会重置通信状态。
举例:
REQUESTED_DEADLINE_MISSED 的flag会变成TRUE,每当新的deadline发生的时候(也会增加total_count)。当调用get_requested_deadline_missed_status时,flag又会重置为FALSE。
2.4.2.2 Read Communication Statuses
对于Read Communication Statuses,StatusChangedFlag默认为FALSE。
StatusChangedFlag在data-sample到达或任何现有sample的ViewState, SampleState或InstanceState因任何原因而更改时变为TRUE,而不是调用DataReader::read, DataReader::take或它们的变体。
下面的事件会使得StatusChangedFlag变为TRUE:
- 新data的到来;
- InstanceState 的改变
- 如DataWriter的OWNERSHIP QoS kind=EXLUSIVE,则通知实例已被拥有该实例的DataWriter处置;
- 如DataWriter的OWNERSHIP QoS kind=SHARED,则通知实例已被任何DataWriter处置;
- instance只有一个DataWriter,该DataWriter的liveliness已丢失;
- 已知正在写入实例的唯一DataWriter unregistered实例的通知到达。
下面的事件会使得StatusChangedFlag变为FALSE:
- DATA_AVAILABLE 的StatusChangedFlag 变成FALSE:当相关的listener调用on_data_available或调用read/take操作;
- DATA_ON_READERS 的StatusChangedFlag 变成FALSE:
- 当相关的listener调用on_data_on_readers;
- on_data_available被DataReader所属的Sub调用;
- read/take操作被调用
2.2.4.3 Access through Listeners
listener提供的是异步的通知,提供的接口如下图:
2.2.4.3.1 Listener Access to Plain Communication Status
2.2.4.3.2 Listener Access to Read Communication Status
2.2.4.4 Conditions and Wait-sets
conditions提供一种中间件能够与APP通信Communication Status改变的方式。
- APP会创建一些感兴趣的condition(StatusCondition,ReadCondition or QueryCondition),并将它们加到WaitSet中。
- 然后APP会wait,直到一个或多个condition的trigger_value变为TRUE。
- 获取trigger_value变为TRUE的condition的list,使用以下的操作:
- 相关的Entity:get_status_changes 之后 get_<communication_status>。如果是一个StatusCondition和他状态的改变,参考plain communication status。
- 相关的Subscriber:get_status_changes之后get_datareaders。如果是一个StatusCondition和他状态的改变,参考 DATA_ON_READERS。
- 相关的DataReader:get_status_changes之后 read/take。如果是一个StatusCondition和他状态的改变,参考 DATA_AVAILABLE。
- 相关的DataReader:如果是ReadCondition 或 QueryCondition,直接使用read_w_condition/take_w_condition。
由于在等待返回时没有额外的信息从中间件传递到应用程序(只有触发的Condition对象列表),Condition对象意味着嵌入在启用时正确响应所需的所有信息。特别是,实体相关的条件只与一个实体相关,不能共享。
WaitSet的blocking操作的行为如下图:
与listeners的调用类似,在唤醒WaitSet时没有隐含的“事件排队”,也就是说,如果附加到WaitSet的几个条件的trigger_value按顺序转换为TRUE,则DCPS实现只需要解除一次WaitSet的阻塞。
2.2.4.4.1 Trigger State of the StatusCondition
StatusCondition的trigger_value是其敏感的所有通信状态的ChangedStatusFlag的布尔或值。trigger_value==FALSE只在所有flag都为FALSE时才可能出现。
StatusCondition对特定通信状态的敏感性由set_enabled_statuses操作在条件上设置的enabled_statuses列表控制。
2.2.4.5 Trigger State of the ReadCondition
与StatusCondition意义,ReadCondition也有trigger_value,这是决定着WaitSet的状态为BLOCKED 或 UNBLOCKED。然而,与StatusCondition不同的是,ReadCondition的trigger_value与至少存在一个由Service管理的样本相关联,其中SampleState、ViewState和InstanceState与ReadCondition的样本相匹配。此外,为了使QueryCondition具有trigger_valueTRUE,与sample相关联的数据必须使query_expression的计算结果为TRUE。
ReadCondition的trigger_value取决于相关DataReader上存在的样本,这意味着单个take()操作可能会改变几个ReadCondition或QueryCondition条件的trigger_value。例如,如果take了所有samples,那么之前与DataReader关联的任何ReadCondition和QueryCondition条件的trigger_valueTRUE将会看到trigger_value变为FALSE。注意,这并不能保证单独附加到这些条件的WaitSet对象不会被唤醒。一旦我们在可能唤醒附加的WaitSet的条件上设置了trigger_valueTRUE,那么将条件转换为trigger_valueFALSE并不一定会“唤醒”WaitSet,因为通常情况下“唤醒”可能是不可能的。结果是,阻塞在WaitSet上的应用程序可能会从等待返回一个条件列表,其中一些条件不再是“active”。如果多个线程并发地等待单独的WaitSet对象并获取与相同DataReader实体关联的数据,这是不可避免的。
为了进一步详细说明,请考虑以下示例:只要有新的样本到达,具有SAMPLE_STATE_MASK={NOT_READ}的ReadCondition就会有TRIGGER_VALUE为TRUE,并且只要所有新到达的样本都被读取(因此它们的状态更改为READ)或被获取(因此它们不再由服务管理),ReadCondition就会转换为FALSE。 然而,如果相同的ReadCondition具有SAMPLE_STATE_MASK={READ,NOT_READ},则Trigger_Value只有在获取了所有新到达的样本后才会变为FALSE(读取它们是不够的,因为这只会将SampleState更改为READ,这与ReadCondition上的掩码重叠。
2.2.4.5.1 Trigger State of the GuardCondition
通过 set_trigger_value改变APP的行为.
2.2.4.6 Combination
这两种机制会组合使用.使用WaitSet和Condition访问数据,并向listener发出错误通信状态的异步警告。
很可能应用程序将为每个特定的通信状态选择一种或另一种机制(而不是两种)。
但是,如果两种机制都启用,则首先使用侦听器机制,然后用信号通知WaitSet对象。
学习资料链接
- FastDDS相关介绍
- OpenDDS 监听器(Listeners)与条件(Conditions)