eProsima Fast DDS 提供了两种不同的 API,用于在不同层次与通信服务进行交互。主要的 API 是数据分发服务(DDS)以数据为中心的发布订阅(DCPS)平台独立模型(PIM)API,简称 DDS DCPS PIM,它由数据分发服务(DDS)1.4 版规范定义,Fast DDS 遵循该规范。本节将专门解释此 API 在 Fast DDS 下的主要特性和使用模式,并深入说明其划分的五个模块:
- 核心模块:定义了由其他模块细化的抽象类和接口。它还提供了服务质量(QoS)定义,以及对与中间件进行基于通知的交互方式的支持。
- 域模块:包含 DomainParticipant 类,它充当服务的入口点,也是许多类的工厂。DomainParticipant 还充当构成服务的其他对象的容器。
- 发布者模块:描述了发布端使用的类,包括 Publisher 和 DataWriter 类,以及 PublisherListener 和 DataWriterListener 接口。
- 订阅者模块:描述了订阅端使用的类,包括 Subscriber 和 DataReader 类,以及 SubscriberListener 和 DataReaderListener 接口。
- 主题模块:描述了用于定义通信主题和数据类型的类,包括 Topic 和 TopicDescription 类,以及 TypeSupport 和 TopicListener 接口。
3.1 核心模块(Core)
此模块定义了将被其他模块使用的基础设施类和类型。它包含了 `Entity` 类、QoS 策略以及状态(Statuses)的定义。
- Entity(实体):Entity 是一种 DDS 通信对象,它具有状态(Status)并可以使用策略(Policies)进行配置。
- Policy(策略):每个控制 Entity 行为的配置对象。
- Status(状态):与 Entity 关联的每个对象,其值代表该 Entity 的通信状态。
3.1.1 Entity(实体)
Entity 是所有 DDS 实体的抽象基类,即支持 QoS 策略、监听器和状态的对象。
3.1.1.1 实体类型
- DomainParticipant:该实体是服务的入口点,并充当 Publisher、Subscriber 和 Topic 的工厂。更多详情,请参阅《DomainParticipant》。
- Publisher:它充当可以创建任意数量 DataWriter 的工厂。更多详情,请参阅《Publisher》。
- Subscriber:它充当可以创建任意数量 DataReader 的工厂。更多详情,请参阅《Subscriber》。
- Topic:该实体位于发布和订阅实体之间,并充当通信渠道。更多详情,请参阅《Topic》。
- DataWriter:是负责数据分发的对象。更多详情,请参阅《DataWriter》。
- DataReader:是用于访问接收数据的对象。更多详情,请参阅《DataReader》。
下图展示了所有 DDS 实体之间的层级关系:

3.1.1.2 实体的共同特性
所有实体类型都共享一些与实体概念相关的共同特性,这些特性包括:
3.1.1.2.1 实体标识符
每个实体都由一个唯一的 ID 标识,该 ID 在 DDS 实体及其对应的 RTPS 实体(如果存在)之间共享。该 ID 存储在 Entity 基类声明的 InstanceHandle 对象中,可以使用 getter 函数 get_instance_handle() 进行访问。
3.1.1.2.2 服务质量(QoS)策略
每个实体的行为可以通过一组配置策略进行设定。对于每种实体类型,都有一个相应的服务质量(QoS)类,该类包含了影响该特定实体类型的所有策略。用户可以创建这些 QoS 类的实例,根据需求修改其中包含的策略,并在创建实体时或之后通过每个实体都暴露的 set_qos() 函数(如 DomainParticipant::set_qos()、Publisher::set_qos()、Subscriber::set_qos()、Topic::set_qos()、DataWriter::set_qos()、DataReader::set_qos())来使用它们配置实体。有关可用策略的列表及其描述,请参阅《策略》。每种实体类型的文档中都详细说明了其对应的 QoS 类及包含的策略。
3.1.1.2.3 监听器
监听器是一个包含回调函数的对象,实体在响应事件时会调用这些函数。因此,监听器充当了一个异步通知系统,允许实体向应用程序通知其状态(Status)的变化。
所有实体类型都定义了一个抽象监听器接口,其中包含了实体为向应用程序传达状态变化而触发的回调函数。用户可以通过继承这些接口并实现其应用程序所需回调函数,来创建自己的监听器。然后,他们可以在创建实体时或之后通过每个实体暴露的 set_listener() 函数(如 DomainParticipant::set_listener()、Publisher::set_listener()、Subscriber::set_listener()、Topic::set_listener()、DataWriter::set_listener()、DataReader::set_listener())将这些监听器链接到每个实体。每种实体类型的监听器接口及其回调函数在每种实体类型的文档中都有说明。当一个事件发生时,它将由最低层级的实体处理,该实体的监听器非空,并且其 StatusMask 中相应的回调已启用。更高级别的监听器从较低级别的监听器继承,如下图所示:

监听器继承关系图。
on_data_on_readers() 回调会在 on_data_available() 之前拦截消息。这意味着如果启用了 DomainParticipantListener,用户应该考虑到默认情况下监听器使用 StatusMask::all()。由于保持了回调实体的层次结构,在这种情况下会调用 on_data_on_readers()。如果应用程序希望改用 on_data_available(),则应禁用 StatusMask 的相应位。
在创建实体时使用 StatusMask::none() 仅会禁用 DDS 标准回调,这些回调包括:
on_sample_rejected()
on_liveliness_changed()
on_requested_deadline_missed()
on_requested_incompatible_qos()
on_data_available()
on_subscription_matched()
on_sample_lost()
on_offered_incompatible_qos()
on_offered_deadline_missed()
on_liveliness_lost()
on_publication_matched()
on_inconsistent_topic()
on_data_on_readers()
任何 Fast DDS 特有的回调始终是启用的。
on_participant_discovery()
onParticipantAuthentication()
on_data_reader_discovery()
on_data_writer_discovery()
on_unacknowledged_sample_removed()
- 只会创建一个线程来监听所有已实现的监听器,因此建议保持监听器函数简单,将此类信息的处理留给适当的类。
- 请勿在监听器成员函数的作用域内创建或删除任何实体,因为这可能导致未定义的行为。建议改为使用监听器类作为信息通道,并使用更上层的实体类来封装此类行为。
3.1.1.2.4 状态
每个实体都与一组状态对象相关联,这些对象的值代表了该实体的通信状态。这些状态值的变化会触发调用相应的监听器回调,以异步方式通知应用程序。有关所有状态对象及其内容的描述列表,请参阅《状态》部分。您还可以在其中找到哪些状态适用于哪些实体类型。
3.1.1.2.5 状态条件
每个实体都拥有一个 StatusCondition,每当其启用的状态发生变化时,该条件变量都会收到通知。StatusCondition 提供了实体与等待集(Wait-set)之间的链接。更多信息,请参阅《条件和等待集》部分。
3.1.1.2.6 启用实体
所有实体都可以被创建为启用或未启用状态。默认情况下,工厂被配置为创建启用的实体,但这可以通过对已启用的工厂使用 EntityFactoryQosPolicy 来更改。一个已禁用的工厂会创建已禁用的实体,无论其 QoS 如何。一个已禁用的实体其操作仅限于以下内容:
- 设置/获取实体的 QoS 策略。
- 设置/获取实体的监听器。
- 创建/删除子实体。
- 获取实体的状态(尽管它们不会改变)。
- 查找操作。
在此状态下调用任何其他函数将返回 NOT_ENABLED
3.1.2 Policy(策略)
服务质量(QoS)用于指定服务的行为,允许用户定义每个实体将如何运作。为了增加系统的灵活性,QoS 被分解为几个可以独立配置的 QoS 策略。但是,可能存在多个策略冲突的情况。这些冲突会通过 QoS 设置函数返回的返回码通知给用户。
每个 QoS 策略在 QosPolicyId_t 枚举器中都有一个唯一的 ID。此 ID 在某些状态实例中用于标识该状态所指的特定 QoS 策略。
有些 QoS 策略是不可变的,这意味着只能在创建实体时或调用 enable 操作之前指定它们。
每个 DDS 实体都有一组特定的 QoS 策略,这些策略可以是标准 QoS 策略、XTypes 扩展和 eProsima 扩展的混合。
3.1.2.1 标准 QoS 策略
本节将逐一说明 DDS 标准的各项 QoS 策略:
3.1.2.1.1 DeadlineQosPolicy
此 QoS 策略在新样本的频率低于某个阈值时发出警报。它适用于预期数据会定期更新的场景(参见 DeadlineQosPolicy)。
在发布端,截止时间定义了预期应用程序提供新样本的最大周期。在订阅端,它定义了应该接收新样本的最大周期。
对于带键(key)的主题,此 QoS 是按键应用的。假设需要定期发布某些车辆的位置。在这种情况下,可以将车辆 ID 设置为数据类型的键,并将 deadline QoS 设置为所需的发布周期。
QoS 策略数据成员列表:
|--------|------------|----------------|
| 数据成员名称 | 类型 | 默认值 |
| period | Duration_t | c_TimeInfinite |
此 QoS 策略适用于 Topic、DataReader 和 DataWriter 实体。
它可以在已启用的实体上更改。
要使 DataWriter 和 DataReader 匹配,它们必须遵循兼容性规则。更多详情,请参阅《兼容性规则》。
兼容性规则
为了维护 DataReader 和 DataWriter 之间 DeadlineQosPolicy 的兼容性,提供的截止时间周期(在 DataWriter 上配置)必须小于或等于请求的截止时间周期(在 DataReader 上配置),否则,这些实体将被视为不兼容。
DeadlineQosPolicy 的设置必须与 TimeBasedFilterQosPolicy 保持一致,这意味着截止时间周期必须大于或等于最小间隔。
示例
// This example uses a DataWriter, but it can also be applied to DataReader and Topic entities
DataWriterQos writer_qos;
// The DeadlineQosPolicy is constructed with an infinite period by default
// Change the period to 1 second
writer_qos.deadline().period.seconds = 1;
writer_qos.deadline().period.nanosec = 0;
// Use modified QoS in the creation of the corresponding entity
writer_ = publisher_->create_datawriter(topic_, writer_qos);
3.1.2.1.2 DestinationOrderQosPolicy
此 QoS 策略将在未来版本中实现。
多个 DataWriter 可以使用相同的键在同一个 Topic 上发送消息,在 DataReader 端,所有这些消息都存储在同一数据实例中(参见 DestinationOrderQosPolicy)。此 QoS 策略控制用于确定这些消息逻辑顺序的标准。系统的行为取决于 DestinationOrderQosPolicyKind 的值。
QoS 策略数据成员列表:
|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------|
| 数据成员名称 | 类型 | 默认值 |
| kind | DestinationOrderQosPolicyKind | BY_RECEPTION_TIMESTAMP_DESTINATIONORDER_QOS |
此 QoS 策略适用于 Topic、DataReader 和 DataWriter 实体。
它不能在已启用的实体上更改。
要使 DataWriter 和 DataReader 匹配,它们必须遵循兼容性规则。更多详情,请参阅《兼容性规则》。
DestinationOrderQosPolicyKind
有两种可能的取值(参见 DestinationOrderQosPolicyKind):
- BY_RECEPTION_TIMESTAMP_DESTINATIONORDER_QOS:这表示数据是基于每个 DataReader 的接收时间排序的,这意味着最后接收到的值应该是被保留的值。此选项可能导致每个 DataReader 最终拥有不同的最终值,因为 DataReaders 可能在不同的时间接收数据。
- BY_SOURCE_TIMESTAMP_DESTINATIONORDER_QOS:这表示数据是基于消息发送时 DataWriter 的时间戳排序的。此选项保证了最终值的一致性。
这两个选项都取决于 OwnershipQosPolicy 和 OwnershipStrengthQosPolicy 的值,这意味着如果所有权设置为 EXCLUSIVE,并且最后一个值来自具有低所有权强度的 DataWriter,它将被丢弃。
兼容性规则
为了在 DataReader 和 DataWriter 的 `DestinationOrderQosPolicy` 具有不同的类型值时保持它们之间的兼容性,DataWriter 的类型必须**高于或等于** DataReader 的类型。不同类型之间的顺序为:
BY_RECEPTION_TIMESTAMP_DESTINATIONORDER_QOS < BY_SOURCE_TIMESTAMP_DESTINATIONORDER_QOS
可能的组合如下表所示:
|---------------------------------------------|---------------------------------------------|---------------|
| DataWriter kind | DataReader kind | Compatibility |
| BY_RECEPTION_TIMESTAMP_DESTINATIONORDER_QOS | BY_RECEPTION_TIMESTAMP_DESTINATIONORDER_QOS | Yes |
| BY_RECEPTION_TIMESTAMP_DESTINATIONORDER_QOS | BY_SOURCE_TIMESTAMP_DESTINATIONORDER_QOS | No |
| BY_SOURCE_TIMESTAMP_DESTINATIONORDER_QOS | BY_RECEPTION_TIMESTAMP_DESTINATIONORDER_QOS | Yes |
| BY_SOURCE_TIMESTAMP_DESTINATIONORDER_QOS | BY_SOURCE_TIMESTAMP_DESTINATIONORDER_QOS | Yes |
3.1.2.1.3 DurabilityQosPolicy
即使网络上没有 DataReader,DataWriter 也可以在整个 Topic 上发送消息。此外,在某些数据写入后加入 Topic 的 DataReader 可能有兴趣访问该信息(参见 DurabilityQosPolicy)。
DurabilityQosPolicy 定义了系统将如何处理在 DataReader 加入 Topic 之前就已存在于 Topic 上的那些样本。系统的行为取决于 DurabilityQosPolicyKind 的值。
QoS 策略数据成员列表:
|--------|-------------------------|--------------------------------------------------------------------------------------------|
| 数据成员名称 | 类型 | 默认值 |
| kind | DurabilityQosPolicyKind | VOLATILE_DURABILITY_QOS for DataReaders TRANSIENT_LOCAL_DURABILITY_QOS for DataWriters |
此 QoS 策略适用于 Topic、DataReader 和 DataWriter 实体。
它不能在已启用的实体上更改。
为了在 DataReader 中接收过去的样本,除了设置此 QoS 策略外,还需要将 ReliabilityQosPolicy 设置为 RELIABLE_RELIABILITY_QOS。
要使 DataWriter 和 DataReader 匹配,它们必须遵循兼容性规则。更多详情,请参阅《兼容性规则》。
DurabilityQosPolicyKind
有四种可能的取值(参见 DurabilityQosPolicyKind):
- VOLATILE_DURABILITY_QOS:过去的样本被忽略,新加入的 DataReader 只接收在其匹配之后生成的样本。
- TRANSIENT_LOCAL_DURABILITY_QOS:当新的 DataReader 加入时,其历史记录(History)会被过去的样本填满。
- TRANSIENT_DURABILITY_QOS:当新的 DataReader 加入时,其历史记录会被过去的样本填满,这些样本存储在持久化存储中(参见《持久化服务》)。
- PERSISTENT_DURABILITY_QOS:当新的 DataReader 加入时,其历史记录会被过去的样本填满,这些样本存储在持久化存储中(参见《持久化服务》)。
兼容性规则
为了在 DataReader 和 DataWriter 的 DurabilityQosPolicy 具有不同的类型值时保持它们之间的兼容性,DataWriter 的类型必须高于或等于 DataReader 的类型。不同类型之间的顺序为:
VOLATILE_DURABILITY_QOS < TRANSIENT_LOCAL_DURABILITY_QOS < TRANSIENT_DURABILITY_QOS < PERSISTENT_DURABILITY_QOS
可能的组合如下表所示:
|--------------------------------|--------------------------------|---------------|
| DataWriter kind | DataReader kind | Compatibility |
| VOLATILE_DURABILITY_QOS | VOLATILE_DURABILITY_QOS | Yes |
| VOLATILE_DURABILITY_QOS | TRANSIENT_LOCAL_DURABILITY_QOS | No |
| VOLATILE_DURABILITY_QOS | TRANSIENT_DURABILITY_QOS | No |
| TRANSIENT_LOCAL_DURABILITY_QOS | VOLATILE_DURABILITY_QOS | Yes |
| TRANSIENT_LOCAL_DURABILITY_QOS | TRANSIENT_LOCAL_DURABILITY_QOS | Yes |
| TRANSIENT_LOCAL_DURABILITY_QOS | TRANSIENT_DURABILITY_QOS | No |
| TRANSIENT_DURABILITY_QOS | VOLATILE_DURABILITY_QOS | Yes |
| TRANSIENT_DURABILITY_QOS | TRANSIENT_LOCAL_DURABILITY_QOS | Yes |
| TRANSIENT_DURABILITY_QOS | TRANSIENT_DURABILITY_QOS | Yes |
示例
// This example uses a DataWriter, but it can also be applied to DataReader and Topic entities
DataWriterQos writer_qos;
// The DurabilityQosPolicy is constructed with kind = VOLATILE_DURABILITY_QOS by default
// Change the kind to TRANSIENT_LOCAL_DURABILITY_QOS
writer_qos.durability().kind = TRANSIENT_LOCAL_DURABILITY_QOS;
// Use modified QoS in the creation of the corresponding entity
writer_ = publisher_->create_datawriter(topic_, writer_qos);
3.1.2.1.4 DurabilityServiceQosPolicy
此 QoS 策略将在未来版本中实现。
当 DurabilityQosPolicy 类型设置为 TRANSIENT_DURABILITY_QOS 或 PERSISTENT_DURABILITY_QOS 时,此 QoS 策略用于配置所使用的虚拟 DataReader 和 DataWriter 的 HistoryQosPolicy 和 ResourceLimitsQosPolicy(参见 DurabilityServiceQosPolicy)。
这些实体用于模拟持久化存储。虚拟的 DataReader 读取写入主题的数据并将其存储,以便如果用户的 DataWriter 没有用户 DataReader 请求的信息,虚拟的 DataWriter 负责发送该信息。
QoS 策略数据成员列表:
|--------------------------|----------------------|-----------------------|
| 数据成员名称 | 类型 | 默认值 |
| service_cleanup_delay | Duration_t | c_TimeZero |
| history_kind | HistoryQosPolicyKind | KEEP_LAST_HISTORY_QOS |
| history_depth | int32_t | 1 |
| max_samples | int32_t | -1 (Length Unlimited) |
| max_instances | int32_t | -1 (Length Unlimited) |
| max_samples_per_instance | int32_t | -1 (Length Unlimited) |
- service_cleanup_delay:它控制服务何时可以移除与某个数据实例相关的所有信息。这些信息将一直保留,直到满足以下所有条件:
- 该实例已被明确释放,并且其 InstanceState 变为 NOT_ALIVE_DISPOSED_INSTANCE_STATE。
- 没有任何存活的 DataWriter 在写入该实例,这意味着所有现有的写入器要么注销了该实例,要么失去了其活性。
- 自服务检测到前两个条件满足以来,已经过去的时间间隔超过了 service_cleanup_delay 中设定的时间。
- history_kind:控制与持久化服务(Durability Service)的虚拟实体关联的 HistoryQosPolicy 的类型。
- history_depth:控制与持久化服务的虚拟实体关联的 HistoryQosPolicy 的深度。
- max_samples:控制与持久化服务的虚拟实体关联的 ResourceLimitsQosPolicy 的最大样本数。此值必须高于每个实例的最大样本数。
- max_instances:控制与持久化服务的虚拟实体关联的 ResourceLimitsQosPolicy 的最大实例数。
- max_samples_per_instance:控制与持久化服务的虚拟实体关联的 ResourceLimitsQosPolicy 中每个实例的最大样本数。此值必须低于最大样本数。
此 QoS 策略适用于 Topic 和 DataWriter 实体。
它不能在已启用的实体上更改。
3.1.2.1.5 EntityFactoryQosPolicy
此 QoS 策略控制实体在作为其他实体的工厂时的行为。默认情况下,所有实体都是在创建时启用的,但如果将 autoenable_created_entities 的值更改为 false,则新实体将被创建为已禁用状态(参见 EntityFactoryQosPolicy)。
QoS 策略数据成员列表:
|-----------------------------|------|------|
| 数据成员名称 | 类型 | 默认值 |
| autoenable_created_entities | bool | true |
此 QoS 策略适用于 DomainParticipantFactory(作为 DomainParticipant 的工厂)、DomainParticipant(作为 Publisher、Subscriber 和 Topic 的工厂)、Publisher(作为 DataWriter 的工厂)和 Subscriber(作为 DataReader 的工厂)。
它可以在已启用的实体上更改,但仅影响更改后创建的实体。
示例
// This example uses a Participant, but it can also be applied to
// DomainParticipantFactory, Publisher and Subscriber entities
DomainParticipantQos participant_qos;
// The EntityFactoryQosPolicy is constructed with autoenable_created_entities = true by default
// Change it to false
participant_qos.entity_factory().autoenable_created_entities = false;
// Use modified QoS in the creation of the corresponding entity
participant_ = factory_->create_participant(domain, participant_qos);
3.1.2.1.6 GroupDataQosPolicy
允许应用程序将附加信息附加到创建的 Publisher 或 Subscriber。此数据对于属于该 Publisher/Subscriber 的所有 DataWriter/DataReader 是通用的,并通过内置主题进行传播(参见 GroupDataQosPolicy)。
此 QoS 策略可以与 DataWriter 和 DataReader 的监听器结合使用,以实现类似于 PartitionQosPolicy 的匹配策略。
QoS 策略数据成员列表:
|------------|------------------------|--------------|
| 数据成员名称 | 类型 | 默认值 |
| collection | std::vector<octet> | Empty vector |
此 QoS 策略适用于 Publisher 和 Subscriber 实体。
它可以在已启用的实体上更改。
示例
// This example uses a Publisher, but it can also be applied to Subscriber entities
PublisherQos publisher_qos;
// The GroupDataQosPolicy is constructed with an empty collection by default
// Collection is a private member so you need to use getters and setters to access
// Add data to the collection in initialization
std::vector<eprosima::fastdds::rtps::octet> vec;
// Add two new octets to group data vector
eprosima::fastdds::rtps::octet val = 3;
vec.push_back(val);
val = 10;
vec.push_back(val);
publisher_qos.group_data().data_vec(vec); // Setter function
// Use modified QoS in the creation of the corresponding entity
publisher_ = participant_->create_publisher(publisher_qos);
// Add data to the collection at runtime
vec = publisher_qos.group_data().data_vec(); // Getter to keep old values
val = 31;
vec.push_back(val);
publisher_qos.group_data().data_vec(vec); // Setter function
// Update the QoS in the corresponding entity
publisher_->set_qos(publisher_qos);
3.1.2.1.7 HistoryQosPolicy
此 QoS 策略控制在实例的值能够成功传达给现有 DataReader 实体之前,该值发生一次或多次变化时系统的行为。
QoS 策略数据成员列表:
|--------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------|
| 数据成员名称 | 类型 | 默认值 |
| kind | HistoryQosPolicyKind | KEEP_LAST_HISTORY_QOS |
| depth | int32_t | 1 |
- kind:控制服务是应仅传递最新值、所有中间值,还是介于两者之间。更多详情,请参阅 HistoryQosPolicyKind。
- depth:确定历史记录中必须保留的最大样本数。仅当 kind 设置为 KEEP_LAST_HISTORY_QOS 时才有效,并且需要与 ResourceLimitsQosPolicy 保持一致,这意味着其值必须小于或等于 max_samples_per_instance。
此 QoS 策略适用于 Topic、DataWriter 和 DataReader 实体。
它不能在已启用的实体上更改。
HistoryQosPolicyKind
有两种可能的取值(参见 HistoryQosPolicyKind):
- KEEP_LAST_HISTORY_QOS:服务将仅尝试保留实例的最新值,并丢弃较旧的值。保留和传递的最大样本数由 HistoryQosPolicy 的深度(depth)定义,该值需要与 ResourceLimitsQosPolicy 设置保持一致。如果达到深度定义的限制,系统将丢弃最旧的样本以为新样本腾出空间。
- KEEP_ALL_HISTORY_QOS:服务将尝试保留实例的所有值,直到这些值能够传递给所有现有的订阅者。如果选择此选项,深度将不再起作用,因此历史记录仅受 ResourceLimitsQosPolicy 中设置的值限制。
兼容性规则
HistoryQos 的设置必须与 ResourceLimitsQosPolicy 保持一致,但也需要与其他 QoS 如 DurabilityQosPolicy 和 ReliabilityQosPolicy 保持一致,因此需要考虑以下几种情况:
- 深度仅在 kind 设置为 KEEP_LAST_HISTORY_QOS 时才会被考虑。
- 深度必须与 ResourceLimitsQosPolicy 的设置保持一致,这意味着深度必须小于或等于 ResourceLimitsQosPolicy 的 max_samples_per_instance。同时,max_samples 必须大于或等于 max_samples_per_instance 乘以 max_instances 的乘积。
- 深度不能小于或等于零。如果需要无限深度,请考虑使用 kind 为 KEEP_ALL_HISTORY_QOS。
- 将 kind 设置为 KEEP_ALL_HISTORY_QOS 意味着限制由 ResourceLimitsQosPolicy 的限制决定(max_samples_per_instance 优先于 max_samples)。
- 在 ReliabilityQosPolicy 的 ReliabilityQosPolicyKind 设置为 RELIABLE_RELIABILITY_QOS 且 HistoryQosPolicy 的类型设置为 KEEP_ALL_HISTORY_QOS 的情况下,当达到资源限制时,服务的行为取决于 DurabilityQosPolicy:
- 如果 DurabilityQosPolicy 的类型配置为 VOLATILE_DURABILITY_QOS,则 DataWriter 的 write() 调用将丢弃历史记录中最旧的样本。请注意,被移除的样本可能属于与新写入的样本不同的实例。
- 如果 DurabilityQosPolicy 的类型配置为 TRANSIENT_LOCAL_DURABILITY_QOS 或 TRANSIENT_DURABILITY_QOS,则 DataWriter 的 write() 调用将被阻塞,直到历史记录中有空间容纳新样本。
示例
// This example uses a DataWriter, but it can also be applied to DataReader and Topic entities
DataWriterQos writer_qos;
// The HistoryQosPolicy is constructed with kind = KEEP_LAST and depth = 1 by default
// It is possible to adjust the depth and keep the kind as KEEP_LAST
writer_qos.history().depth = 20;
// Or you can also change the kind to KEEP_ALL (depth will not be used).
writer_qos.history().kind = KEEP_ALL_HISTORY_QOS;
// Use modified QoS in the creation of the corresponding entity
writer_ = publisher_->create_datawriter(topic_, writer_qos);
3.1.2.1.8 LatencyBudgetQosPolicy
此 QoS 策略将在未来版本中实现。
此 QoS 策略规定了从数据被写入时起,到数据被插入 DataReader 历史记录并得到通知为止,所能接受的最大延迟。默认情况下,该延迟设置为 0,以优化内部操作(参见 LatencyBudgetQosPolicy)。
QoS 策略数据成员列表:
|----------|------------|------------|
| 数据成员名称 | 类型 | 默认值 |
| duration | Duration_t | c_TimeZero |
此 QoS 策略适用于 Topic、DataWriter 和 DataReader 实体。
它可以在已启用的实体上更改。
要使 DataWriter 和 DataReader 匹配,它们必须遵循兼容性规则。更多详情,请参阅《兼容性规则》。
兼容性规则
为了保持 DataReader 和 DataWriter 之间 LatencyBudgetQosPolicy 的兼容性,DataWriter 的持续时间必须小于或等于 DataReader 的持续时间。
3.1.2.1.9 LifespanQosPolicy
每个由 DataWriter 写入的数据样本都有一个关联的过期时间,超过该时间后,数据将从 DataWriter 和 DataReader 的历史记录以及临时和持久信息缓存中移除(参见 LifespanQosPolicy)。
默认情况下,持续时间是无限的,这意味着 DataWriter 写入的样本的有效期没有最大时长限制。
过期时间是通过将持续时间(duration)添加到源时间戳来计算的。源时间戳可以在调用 write() 成员函数时自动计算,也可以通过应用程序使用 write_w_timestamp() 成员函数提供。DataReader 允许使用接收时间戳代替源时间戳。
QoS 策略数据成员列表:
|----------|------------|----------------|
| 数据成员名称 | 类型 | 默认值 |
| duration | Duration_t | c_TimeInfinite |
此 QoS 策略适用于 Topic、DataReader 和 DataWriter 实体。
它可以在已启用的实体上更改。
示例
// This example uses a DataWriter, but it can also be applied to DataReader and Topic entities
DataWriterQos writer_qos;
// The LifespanQosPolicy is constructed with duration set to infinite by default
// Change the duration to 5 s
writer_qos.lifespan().duration = {5, 0};
// Use modified QoS in the creation of the corresponding entity
writer_ = publisher_->create_datawriter(topic_, writer_qos);
3.1.2.1.10 LivelinessQosPolicy
此 QoS 策略控制服务用于确保网络上特定实体仍然存活(alive)的机制。不同的设置可以区分数据周期性更新的应用程序和数据零星变化的应用程序。它还允许针对活性机制应检测的故障类型来自定义应用程序(参见 LivelinessQosPolicy)。
QoS 策略数据成员列表:
| Data Member Name | Type | Default Value |
|---|---|---|
kind |
LivelinessQosPolicyKind | AUTOMATIC_LIVELINESS_QOS |
lease_duration |
Duration_t |
c_TimeInfinite |
announcement_period |
Duration_t |
c_TimeInfinite |
- kind:此数据成员确定服务是需要自动断言活性,还是需要等待发布端断言活性。更多详情,请参阅 LivelinessQosPolicyKind。
- lease_duration:自 DataWriter 上次断言其活性以来,等待其被认为不再存活所经过的时间量。
- announcement_period:DataWriter 发送的连续活性消息之间的时间间隔。此数据成员仅在 kind 为 AUTOMATIC_LIVELINESS_QOS 或 MANUAL_BY_PARTICIPANT_LIVELINESS_QOS 时生效,并且需要小于 lease_duration。
此 QoS 策略适用于 Topic、DataReader 和 DataWriter 实体。
它不能在已启用的实体上更改。
要使 DataWriter 和 DataReader 匹配,它们必须遵循兼容性规则。更多详情,请参阅《兼容性规则》。
LivelinessQosPolicyKind
有三种可能的取值(参见 LivelinessQosPolicyKind):
- AUTOMATIC_LIVELINESS_QOS:只要运行参与者的本地进程以及连接它与远程参与者的链路存在,服务就负责按所需速率更新租约,远程参与者内的实体将被视为存活。这种类型适用于仅需要检测远程应用程序是否仍在运行的应用程序。
- 两种手动模式要求发布端的应用程序在 lease_duration 定时器到期前定期断言活性。发布任何新数据值都会隐式地断言 DataWriter 的活性,但也可以通过调用 assert_liveliness 成员函数来显式地执行。
- MANUAL_BY_PARTICIPANT_LIVELINESS_QOS:如果发布端的某个实体断言其活性,服务将推断同一 DomainParticipant 内的所有其他实体也都是存活的。
- MANUAL_BY_TOPIC_LIVELINESS_QOS:此模式限制性更强,要求 DataWriter 内至少有一个实例被断言,才能认为该 DataWriter 是存活的。
兼容性规则
为了在 DataReader 和 DataWriter 之间保持 LivelinessQosPolicy 的兼容性,DataWriter 的类型必须高于或等于 DataReader 的类型。不同类型之间的顺序为:
AUTOMATIC_LIVELINESS_QOS < MANUAL_BY_PARTICIPANT_LIVELINESS_QOS < MANUAL_BY_TOPIC_LIVELINESS_QOS
可能的组合如下表所示:
| DataWriter kind | DataReader kind | Compatibility |
|---|---|---|
AUTOMATIC_LIVELINESS_QOS |
AUTOMATIC_LIVELINESS_QOS |
Yes |
AUTOMATIC_LIVELINESS_QOS |
MANUAL_BY_PARTICIPANT_LIVELINESS_QOS |
No |
AUTOMATIC_LIVELINESS_QOS |
MANUAL_BY_TOPIC_LIVELINESS_QOS |
No |
MANUAL_BY_PARTICIPANT_LIVELINESS_QOS |
AUTOMATIC_LIVELINESS_QOS |
Yes |
MANUAL_BY_PARTICIPANT_LIVELINESS_QOS |
MANUAL_BY_PARTICIPANT_LIVELINESS_QOS |
Yes |
MANUAL_BY_PARTICIPANT_LIVELINESS_QOS |
MANUAL_BY_TOPIC_LIVELINESS_QOS |
No |
MANUAL_BY_TOPIC_LIVELINESS_QOS |
AUTOMATIC_LIVELINESS_QOS |
Yes |
MANUAL_BY_TOPIC_LIVELINESS_QOS |
MANUAL_BY_PARTICIPANT_LIVELINESS_QOS |
Yes |
MANUAL_BY_TOPIC_LIVELINESS_QOS |
MANUAL_BY_TOPIC_LIVELINESS_QOS |
Yes |
此外,DataWriter 的 lease_duration 不得大于 DataReader 的 lease_duration。
示例
// This example uses a DataWriter, but it can also be applied to DataReader and Topic entities
DataWriterQos writer_qos;
// The LivelinessQosPolicy is constructed with kind = AUTOMATIC by default
// Change the kind to MANUAL_BY_PARTICIPANT
writer_qos.liveliness().kind = MANUAL_BY_PARTICIPANT_LIVELINESS_QOS;
// The LivelinessQosPolicy is constructed with lease_duration set to infinite by default
// Change the lease_duration to 1 second
writer_qos.liveliness().lease_duration = {1, 0};
// The LivelinessQosPolicy is constructed with announcement_period set to infinite by default
// Change the announcement_period to 1 ms
writer_qos.liveliness().announcement_period = {0, 1000000};
// Use modified QoS in the creation of the corresponding entity
writer_ = publisher_->create_datawriter(topic_, writer_qos);
3.1.2.1.11 OwnershipQosPolicy
此 QoS 策略指定是否允许多个 DataWriter 更新同一数据实例,如果允许,应如何仲裁这些修改(参见 OwnershipQosPolicy)。
QoS 策略数据成员列表:
|--------|------------------------|----------------------|
| 数据成员名称 | 类型 | 默认值 |
| kind | OwnershipQosPolicyKind | SHARED_OWNERSHIP_QOS |
此 QoS 策略适用于 Topic、DataReader 和 DataWriter 实体。
它不能在已启用的实体上更改。
要使 DataWriter 和 DataReader 匹配,它们必须遵循兼容性规则。更多详情,请参阅《兼容性规则》。
OwnershipQosPolicyKind
有两种可能的取值(参见 OwnershipQosPolicyKind):
- SHARED_OWNERSHIP_QOS:此选项表示服务不强制对每个实例拥有唯一所有权。在这种情况下,允许多个 DataWriter 更新同一数据实例,并且所有更新都对现有的 DataReader 可用。这些更新也受 TimeBasedFilterQosPolicy 或 HistoryQosPolicy 设置的影响,因此可以被过滤。
- EXCLUSIVE_OWNERSHIP_QOS:此选项表示每个实例只能由一个 DataWriter 更新,这意味着在任何时间点,单个 DataWriter 拥有每个实例,并且只有其修改对现有的 DataReader 可见。所有者可以根据存活的 DataWriter 之间的最高强度动态更改,前提是这些 DataWriter 未违反关于数据实例的截止时间约定。该强度可以使用 OwnershipStrengthQosPolicy 进行更改。如果两个 DataWriter 具有相同的强度值,则 GUID 值较低的 DataWriter 将成为该主题的所有者。
兼容性规则
为了保持 DataReader 和 DataWriter 之间 OwnershipQosPolicy 的兼容性,DataWriter 的类型必须等于 DataReader 的类型。
可能的组合如下表所示:
| DataWriter kind | DataReader kind | Compatibility |
|---|---|---|
SHARED_OWNERSHIP_QOS |
SHARED_OWNERSHIP_QOS |
Yes |
SHARED_OWNERSHIP_QOS |
EXCLUSIVE_OWNERSHIP_QOS |
No |
EXCLUSIVE_OWNERSHIP_QOS |
SHARED_OWNERSHIP_QOS |
No |
EXCLUSIVE_OWNERSHIP_QOS |
EXCLUSIVE_OWNERSHIP_QOS |
Yes |
示例
// This example uses a DataWriter, but it can also be applied to DataReader and Topic entities
DataWriterQos writer_qos;
// The OwnershipQosPolicy is constructed with kind = SHARED by default
// Change the kind to EXCLUSIVE
writer_qos.ownership().kind = EXCLUSIVE_OWNERSHIP_QOS;
// Use modified QoS in the creation of the corresponding entity
writer_ = publisher_->create_datawriter(topic_, writer_qos);
3.1.2.1.12 OwnershipStrengthQosPolicy
此 QoS 策略指定了用于仲裁多个尝试修改同一数据实例的 DataWriter 的强度值。仅在 OwnershipQosPolicy 类型设置为 EXCLUSIVE_OWNERSHIP_QOS 时适用。参见 OwnershipStrengthQosPolicy。
QoS 策略数据成员列表:
|--------|----------|-----|
| 数据成员名称 | 类型 | 默认值 |
| value | uint32_t | 0 |
此 QoS 策略适用于 DataWriter 实体。
它可以在已启用的实体上更改。
示例
// This example only applies to DataWriter entities
DataWriterQos writer_qos;
// The OwnershipStrengthQosPolicy is constructed with value 0 by default
// Change the strength to 10
writer_qos.ownership_strength().value = 10;
// Use modified QoS in the creation of the corresponding DataWriter
writer_ = publisher_->create_datawriter(topic_, writer_qos);
3.1.2.1.13 PartitionQosPolicy
此 QoS 策略允许在域引入的物理分区内引入逻辑分区。对于 DataReader 来说,要看到 DataWriter 所做的更改,不仅主题必须匹配,而且它们还必须共享至少一个逻辑分区(参见 PartitionQosPolicy)。
空字符串也被视为有效的分区名称,并且它使用与任何其他分区名称相同的字符串匹配和正则表达式匹配规则进行匹配。
QoS 策略数据成员列表:
| 数据成员名称 | 类型 | 默认值 |
|---|---|---|
max_size |
uint32_t |
0 (Length Unlimited) |
names |
SerializedPayload_t |
Empty List |
- max_size:分区名称列表的最大大小。
- names:分区名称的列表。
此 QoS 策略适用于 Publisher 和 Subscriber 实体。
也可以在端点(endpoint)级别显式定义分区以覆盖此配置。相关信息可在此处找到。
它可以在已启用的实体上更改。
示例
// This example uses a Publisher, but it can also be applied to Subscriber entities
PublisherQos publisher_qos;
// The PartitionsQosPolicy is constructed with max_size = 0 by default
// Max_size is a private member so you need to use getters and setters to access
// Change the max_size to 20
publisher_qos.partition().set_max_size(20); // Setter function
// The PartitionsQosPolicy is constructed with an empty list of partitions by default
// Partitions is a private member so you need to use getters and setters to access
// Add new partitions in initialization
std::vector<std::string> part;
part.push_back("part1");
part.push_back("part2");
publisher_qos.partition().names(part); // Setter function
// Use modified QoS in the creation of the corresponding entity
publisher_ = participant_->create_publisher(publisher_qos);
// Add data to the collection at runtime
part = publisher_qos.partition().names(); // Getter to keep old values
part.push_back("part3");
publisher_qos.partition().names(part); // Setter function
// Update the QoS in the corresponding entity
publisher_->set_qos(publisher_qos);
3.1.2.1.14 PresentationQosPolicy
此 QoS 策略将在未来版本中实现。
此 QoS 策略规定了代表数据实例变更的样本如何呈现给订阅应用程序。它控制着数据实例的变更在多大程度上可以相互依赖,以及可以传播和维护的依赖类型。参见 PresentationQosPolicy。
QoS 策略数据成员列表:
| 数据成员名称 | 类型 | 默认值 |
|---|---|---|
access_scope |
PresentationQosPolicyAccessScopeKind | INSTANCE_PRESENTATION_QOS |
coherent_access |
bool |
false |
ordered_access |
bool |
false |
- access_scope:确定可以保持顺序和一致性的最大实体范围。更多详情,请参阅 PresentationQosPolicyAccessScopeKind。
- coherent_access:控制服务是否会保留发布端所做的变更分组,以便在订阅端将它们作为一个整体接收。
- ordered_access:控制服务是否支持订阅者以与发布端发生顺序相同的顺序查看变更。
此 QoS 策略适用于 Publisher 和 Subscriber 实体。
它不能在已启用的实体上更改。
要使 DataWriter 和 DataReader 匹配,它们必须遵循兼容性规则。更多详情,请参阅《兼容性规则》。
PresentationQosPolicyAccessScopeKind
有三种可能的取值,其行为取决于 coherent_access 和 ordered_access 变量的值(参见 PresentationQosPolicyAccessScopeKind):
- INSTANCE_PRESENTATION_QOS:对某个数据实例的变更不需要与对其他任何实例的变更保持一致性或顺序性,这意味着顺序和一致性变更分别应用于每个实例。
- 在此情况下启用 coherent_access 对订阅者访问数据的方式没有影响,因为范围仅限于每个实例,对不同实例的变更被认为是独立的,因此不能通过一致性变更进行分组。
- 在此情况下启用 ordered_access 仅影响同一实例内的变更。因此,即使由同一个应用程序线程和 DataWriter 执行,对两个实例所做的变更也不一定按发生的顺序被看到。
- TOPIC_PRESENTATION_QOS:范围扩展到同一 DataWriter 内的所有实例。
- 启用 coherent_access 后,在同一 DataWriter 内对实例进行的分组变更将作为一个整体,与该 DataWriter 中对其他实例的变更保持一致性,但不会与属于不同 DataWriter 的实例的变更进行分组。
- 启用 ordered_access 意味着单个 DataWriter 所做的变更按发生顺序提供给订阅者,但通过不同 DataWriter 对实例所做的变更不一定会按顺序被看到。
- GROUP_PRESENTATION_QOS:范围扩展到属于同一 Publisher 内的所有 DataWriter 的实例。
- 启用 coherent_access 意味着通过附加到同一 Publisher 的 DataWriter 对实例进行的一致性变更,将作为一个整体提供给远程订阅者。
- 在此范围内启用 ordered_access 可使附加到同一 Publisher 的任何 DataWriter 所做的变更按发生顺序提供给订阅者。
兼容性规则
为了保持 DataReader 和 DataWriter 之间 PresentationQosPolicy 的兼容性,Publisher 的 access_scope 必须高于或等于 Subscriber 的 access_scope。不同访问范围之间的顺序为:
INSTANCE_PRESENTATION_QOS < TOPIC_PRESENTATION_QOS < GROUP_PRESENTATION_QOS
可能的组合如下表所示:
| Publisher scope | Subscriber scope | Compatibility |
|---|---|---|
INSTANCE_PRESENTATION_QOS |
INSTANCE_PRESENTATION_QOS |
Yes |
INSTANCE_PRESENTATION_QOS |
TOPIC_PRESENTATION_QOS |
No |
INSTANCE_PRESENTATION_QOS |
GROUP_PRESENTATION_QOS |
No |
TOPIC_PRESENTATION_QOS |
INSTANCE_PRESENTATION_QOS |
Yes |
TOPIC_PRESENTATION_QOS |
TOPIC_PRESENTATION_QOS |
Yes |
TOPIC_PRESENTATION_QOS |
GROUP_PRESENTATION_QOS |
No |
GROUP_PRESENTATION_QOS |
INSTANCE_PRESENTATION_QOS |
Yes |
GROUP_PRESENTATION_QOS |
TOPIC_PRESENTATION_QOS |
Yes |
GROUP_PRESENTATION_QOS |
GROUP_PRESENTATION_QOS |
Yes |
此外,只有当 Publisher 上也启用了 `coherent_access` 和 `ordered_access` 时,Subscriber 才能启用它们。
3.1.2.1.15 ReaderDataLifecycleQosPolicy
此 QoS 策略将在未来版本中实现。
此 QoS 策略规定了 DataReader 关于其管理的数据实例生命周期的行为,即已经接收到的、且 DataReader 为其维护了一些内部资源的实例。DataReader 会保留应用程序尚未取走的样本,这受 HistoryQosPolicy 和 ResourceLimitsQosPolicy 施加的约束限制。参见 ReaderDataLifecycleQosPolicy。
在正常情况下,如果不存在写入器且所有样本都已被取走,DataReader 才能回收与数据实例关联的资源。但如果应用程序未取走这些样本,服务将阻止 DataReader 回收资源,导致这些资源无限期地保留在 DataReader 中。此 QoS 的存在就是为了避免这种情况。
QoS 策略数据成员列表:
| 数据成员名称 | 类型 | 默认值 |
|---|---|---|
autopurge_no_writer_samples_delay |
Duration_t |
c_TimeInfinite |
autopurge_disposed_samples_delay |
Duration_t |
c_TimeInfinite |
- autopurge_no_writer_samples_delay:定义一旦实例的 instance_state 变为 NOT_ALIVE_NO_WRITERS_INSTANCE_STATE 后,DataReader 必须保留该实例信息的最长持续时间。超过此时间后,DataReader 将清除该实例的所有内部信息,包括将被丢失的未取走样本。
- autopurge_disposed_samples_delay:定义一旦实例的 instance_state 变为 NOT_ALIVE_DISPOSED_INSTANCE_STATE 后,DataReader 必须保留该实例信息的最长持续时间。超过此时间后,DataReader 将清除该实例的所有样本。
此 QoS 策略适用于 DataReader 实体。
它可以在已启用的实体上更改。
3.1.2.1.16 ReliabilityQosPolicy
此 QoS 策略表示服务提供和请求的可靠性级别。参见 ReliabilityQosPolicy。
QoS 策略数据成员列表:
| 数据成员名称 | 类型 | 默认值 |
|---|---|---|
kind |
ReliabilityQosPolicyKind | BEST_EFFORT_RELIABILITY_QOS for DataReaders RELIABLE_RELIABILITY_QOS for DataWriters |
max_blocking_time |
Duration_t |
100 ms |
- kind:指定服务在样本交付方面的行为。更多详情,请参阅 ReliabilityQosPolicyKind。
- max_blocking_time:配置写入操作可以被阻塞的最大持续时间。
此 QoS 策略适用于 Topic、DataWriter 和 DataReader 实体。
它不能在已启用的实体上更改。
将此 QoS 策略设置为 BEST_EFFORT_RELIABILITY_QOS 会影响 DurabilityQosPolicy,使端点表现为 VOLATILE_DURABILITY_QOS。
要使 DataWriter 和 DataReader 匹配,它们必须遵循兼容性规则。更多详情,请参阅《兼容性规则》。
ReliabilityQosPolicyKind
有两种可能的取值(ReliabilityQosPolicyKind):
- BEST_EFFORT_RELIABILITY_QOS:表示可以不重传丢失的样本,因此消息发送时无需等待送达确认。通常样本的新值生成足够频繁,以至于没有必要重新发送任何样本。但是,由同一 DataWriter 发送的数据样本将按它们发生的顺序存储在 DataReader 的历史记录中。换句话说,即使 DataReader 丢失了一些数据样本,较旧的值也绝不会覆盖较新的值。
- RELIABLE_RELIABILITY_QOS:表示服务将尝试传递 DataWriter 历史记录中的所有样本,并期望从 DataReader 获得送达确认。如果之前有尚未接收到的样本,则同一 DataWriter 发送的数据样本就无法提供给 DataReader。服务将重传丢失的数据样本,以便在 DataReader 可以访问之前,重建 DataWriter 历史记录的正确快照。此选项可能会阻塞写入操作,因此设置了 max_blocking_time,一旦时间到期,写入操作将被解除阻塞。但是,如果在数据发送之前 max_blocking_time 到期,写入操作将返回一个错误
兼容性规则
为了在 DataReader 和 DataWriter 之间保持 ReliabilityQosPolicy 的兼容性,DataWriter 的类型必须高于或等于 DataReader 的类型。不同类型之间的顺序为:
BEST_EFFORT_RELIABILITY_QOS < RELIABLE_RELIABILITY_QOS
可能的组合如下表所示:
| DataWriter kind | DataReader kind | Compatibility |
|---|---|---|
BEST_EFFORT_RELIABILITY_QOS |
BEST_EFFORT_RELIABILITY_QOS |
Yes |
BEST_EFFORT_RELIABILITY_QOS |
RELIABLE_RELIABILITY_QOS |
No |
RELIABLE_RELIABILITY_QOS |
BEST_EFFORT_RELIABILITY_QOS |
Yes |
RELIABLE_RELIABILITY_QOS |
RELIABLE_RELIABILITY_QOS |
Yes |
示例
// This example uses a DataWriter, but it can also be applied to DataReader and Topic entities
DataWriterQos writer_qos;
// The ReliabilityQosPolicy is constructed with kind = BEST_EFFORT by default
// Change the kind to RELIABLE
writer_qos.reliability().kind = RELIABLE_RELIABILITY_QOS;
// The ReliabilityQosPolicy is constructed with max_blocking_time = 100ms by default
// Change the max_blocking_time to 1s
writer_qos.reliability().max_blocking_time = {1, 0};
// Use modified QoS in the creation of the corresponding entity
writer_ = publisher_->create_datawriter(topic_, writer_qos);
3.1.2.1.17 ResourceLimitsQosPolicy
此 QoS 策略控制服务可用于满足应用程序和其他 QoS 策略所施加要求的资源。参见 ResourceLimitsQosPolicy。
QoS 策略数据成员列表:
| 数据成员名称 | 类型 | 默认值 |
|---|---|---|
max_samples |
int32_t |
-1 (Length Unlimited) |
max_instances |
int32_t |
-1 (Length Unlimited) |
max_samples_per_instance |
int32_t |
-1 (Length Unlimited) |
allocated_samples |
int32_t |
100 |
extra_samples |
int32_t |
1 |
- max_samples:控制 DataWriter 或 DataReader 可以管理与其关联的所有实例的最大样本数。换句话说,它表示中间件可以为 DataReader 或 DataWriter 存储的最大样本数。值小于或等于 0 表示资源无限。
- max_instances:控制 DataWriter 或 DataReader 可以管理的最大实例数。对于无键主题,此值将在内部固定为 1。值小于或等于 0 表示资源无限。
- max_samples_per_instance:控制 DataWriter 或 DataReader 可以管理的每个实例内的最大样本数。对于无键主题,此值将被忽略(将使用 max_samples 代替)。值小于或等于 0 表示资源无限。
- allocated_samples:指定初始化时将分配的样本数量。将受 max_samples 限制(即使用两者中的最小值)。
- extra_samples:指定将在池中分配的额外样本数量,因此池中的最大样本数将为 max_samples 加上 extra_samples。这些额外样本即使在历史记录已满时也能充当样本储备池。
此 QoS 策略适用于 Topic、DataWriter 和 DataReader 实体。
它不能在已启用的实体上更改。
兼容性规则
为了保持 ResourceLimitsQosPolicy 内部的兼容性,数据成员的值必须满足以下条件:
- max_samples 的值必须大于或等于 max_samples_per_instance 的值。
- HistoryQosPolicy 的 depth 设置的值必须小于或等于 max_samples_per_instance 声明的值。
示例
// This example uses a DataWriter, but it can also be applied to DataReader and Topic entities
DataWriterQos writer_qos;
// The ResourceLimitsQosPolicy is constructed with max_samples = LENGTH_UNLIMITED by default
// Change max_samples to 2000
writer_qos.resource_limits().max_samples = 2000;
// The ResourceLimitsQosPolicy is constructed with max_instances = LENGTH_UNLIMITED by default
// Change max_instances to 20
writer_qos.resource_limits().max_instances = 20;
// The ResourceLimitsQosPolicy is constructed with max_samples_per_instance = LENGTH_UNLIMITED by default
// Change max_samples_per_instance to 100
writer_qos.resource_limits().max_samples_per_instance = 100;
// The ResourceLimitsQosPolicy is constructed with allocated_samples = 100 by default
// Change allocated_samples to 50
writer_qos.resource_limits().allocated_samples = 50;
// Use modified QoS in the creation of the corresponding entity
writer_ = publisher_->create_datawriter(topic_, writer_qos);
3.1.2.1.18 TimeBasedFilterQosPolicy
此 QoS 策略将在未来版本中实现。
过滤器,允许 DataReader 指定其仅对数据的某个子集感兴趣。此过滤器表明,无论变化发生得多快,DataReader 在每个 minimum_separation 时间内不希望收到超过一个值。参见 TimeBasedFilterQosPolicy。
minimum_separation 必须小于 DeadlineQosPolicy 的周期。默认情况下,minimum_separation 为零,这意味着 DataReader 可能对所有值都感兴趣。
QoS 策略数据成员列表:
| 数据成员名称 | 类型 | 默认值 |
|---|---|---|
minimum_separation |
Duration_t |
c_TimeZero |
此 QoS 策略适用于 DataReader 实体。
它可以在已启用的实体上更改。
3.1.2.1.19 TopicDataQosPolicy
允许应用程序将附加信息附加到已创建的 Topic,以便当远程应用程序发现该 Topic 时,它可以访问并使用这些数据。参见 TopicDataQosPolicy。
QoS 策略数据成员列表:
| 数据成员名称 | 类型 | 默认值 |
|---|---|---|
| collection | std::vector<octet> |
Empty vector |
此 QoS 策略适用于 Topic 实体。
即使它已经创建,也可以更改。
示例
// This example only applies to Topic entities
TopicQos topic_qos;
// The TopicDataQosPolicy is constructed with an empty vector by default
std::vector<eprosima::fastdds::rtps::octet> vec;
// Add two new octets to topic data vector
eprosima::fastdds::rtps::octet val = 3;
vec.push_back(val);
val = 10;
vec.push_back(val);
topic_qos.topic_data().data_vec(vec); // Setter Function
// Use modified QoS in the creation of the corresponding Topic
topic_ = participant_->create_topic("<topic_name>", "<type_name>", topic_qos);
3.1.2.1.20 TransportPriorityQosPolicy
此 QoS 策略的目的是让服务能够利用那些支持以不同优先级发送消息的传输方式。它设定了用于发送数据的底层传输的优先级。参见 TransportPriorityQosPolicy。
您可以在 32 位范围内为优先级选择任意值。值越高,优先级越高。
QoS 策略数据成员列表:
| 数据成员名称 | 类型 | 默认值 |
|---|---|---|
value |
int32_t |
0 |
此 QoS 策略适用于 Topic 和 DataWriter 实体。
它可以在已启用的实体上更改。
示例
// This example only applies to DataWriter entities
DataWriterQos writer_qos;
// The TransportPriorityQosPolicy is constructed with value 0 by default
// Change the value to 12
writer_qos.transport_priority().value = 12;
// Use modified QoS in the creation of the corresponding DataWriter
writer_ = publisher_->create_datawriter(topic_, writer_qos);
// Change the TransportPriorityQosPolicy at runtime
writer_qos.transport_priority().value = 23;
// Update the QoS in the corresponding entity
writer_->set_qos(writer_qos);
3.1.2.1.21 UserDataQosPolicy
允许应用程序将附加信息附加到 Entity 对象,以便当该实体被发现时,远程应用程序可以访问并使用这些数据。例如,它可以用于附加安全凭证,以对来自远程应用程序的来源进行身份验证。参见 UserDataQosPolicy。
QoS 策略数据成员列表:
| 数据成员名称 | 类型 | 默认值 |
|---|---|---|
| collection | std::vector<octet> |
Empty vector |
此 QoS 策略适用于 DomainParticipant、DataWriter 和 DataReader 实体。
它可以在已启用的实体上更改。
示例
// This example uses a DataWriter, but it can also be applied to DomainParticipant and DataReader entities
DataWriterQos writer_qos;
std::vector<eprosima::fastdds::rtps::octet> vec;
// Add two new octets to user data vector
eprosima::fastdds::rtps::octet val = 3;
vec.push_back(val);
val = 10;
vec.push_back(val);
writer_qos.user_data().data_vec(vec); // Setter Function
// Use modified QoS in the creation of the corresponding entity
writer_ = publisher_->create_datawriter(topic_, writer_qos);
3.1.2.1.22 WriterDataLifecycleQosPolicy
此 QoS 策略将在未来版本中实现。
此 QoS 策略规定了 DataWriter 关于其管理的数据实例生命周期的行为,即通过 register 操作显式注册或直接写入数据而隐式注册到 DataWriter 的实例。
autodispose_unregistered_instances 控制 DataWriter 是否会在每次注销实例时自动处置该实例。即使禁用了此选项,如果应用程序在注销实例之前使用了 dispose 操作,仍然可以获得相同的结果。
QoS 策略数据成员列表
| 数据成员名称 | 类型 | 默认值 |
|---|---|---|
autodispose_unregistered_instances |
bool |
true |
此 QoS 策略适用于 DataWriter 实体。
它可以在已启用的实体上更改。
3.1.2.2 eProsima 扩展
eProsima QoS 策略扩展是指那些允许更改 RTPS 层可配置设置值的策略。
3.1.2.2.1 DataSharingQosPolicy
此附加 QoS 允许配置写入器和读取器之间的数据共享(Data-sharing)交付通信。有关数据共享交付功能的描述,请参阅《数据共享交付》。
QoS 策略数据成员列表:
| Data Member | Type | Accessor | Default Value |
|---|---|---|---|
| Data-sharing kind | DataSharingKind | kind() |
AUTO |
| Shared memory directory | string |
shm_directory() |
Empty string |
| Maximum domain number | uint32_t |
max_domains() |
0 (unlimited) |
| Data-sharing domain IDs | vector<uint64_t> |
domain_ids() |
Empty |
| Data-sharing listener thread settings | ThreadSettings | data_sharing_listener_thread() |
- 数据共享类型:指定数据共享交付的行为。有关可能的值及其影响的描述,请参阅 DataSharingKind。
- 共享内存目录:将用于内存映射文件的目录。如果未配置,则使用系统默认目录。
- 最大域数量:确定本地或远程端点中数据共享域 ID 的最大数量。域 ID 在数据共享交付兼容的端点之间交换。如果此值低于任何远程端点的列表大小,匹配可能会失败。值为零表示无限制的 ID 数量。
- 数据共享域 ID 列表:为当前 DataWriter 或 DataReader 配置的数据共享域 ID 列表。如果未提供 ID,系统将为当前机器创建一个唯一的 ID。
- 数据共享监听器线程设置:专用于监听传入流量的数据共享线程的 ThreadSettings。
此 QoS 策略适用于 DataWriter 和 DataReader 实体。
它不能在已启用的实体上更改。
DataSharingKind
有三种可能的取值(参见 DataSharingKind):
- OFF:数据共享交付被禁用。将不会使用数据共享交付功能进行任何通信。
- ON:手动启用数据共享交付。如果当前主题与数据共享交付不兼容,将会发生错误。与共享至少一个数据共享域 ID 的远程实体的通信将使用数据共享交付功能进行。
- AUTO:如果当前主题与数据共享兼容,则将激活数据共享交付;如果不兼容,则禁用它。
数据共享配置辅助函数
为了设置数据共享交付配置,必须使用以下辅助成员函数之一。每种 DataSharingKind 类型都有一个对应的函数:
| Function | Resulting DataSharingKind | Shared memory directory | Data sharing domain IDs |
|---|---|---|---|
automatic() |
AUTO |
Optional | Optional |
on() |
ON |
Mandatory | Optional |
off() |
OFF |
N/A | N/A |
除了在这些辅助函数中定义数据共享域 ID 之外,您还可以稍后使用 add_domain_id() 函数添加它们。请注意,添加新的域 ID 算作修改 QoS 策略,因此必须在实体启用之前完成。
示例
// This example uses a DataWriter, but it can also be applied to DataReader entities
DataWriterQos writer_qos;
// DataSharing is set to AUTO by default, which means that DataSharing will be used if the topic
// is compatible. If no Shared Memory directory is specified, the default one will be used.
// Configure DataSharing to ON to enable DataSharing and specify the shared memory directory (mandatory)
writer_qos.data_sharing().on("/path/to/shared_memory/directory");
// Alternatively, configure DataSharing to OFF to disable it
writer_qos.data_sharing().off();
// Configure the DataSharing as AUTO with two user-defined IDs (can also be used with ON)
std::vector<uint16_t> ids;
ids.push_back(0x1234);
ids.push_back(0xABCD);
writer_qos.data_sharing().automatic(ids);
// Alternatively, add them individually
writer_qos.data_sharing().add_domain_id(uint16_t(0x1234));
writer_qos.data_sharing().add_domain_id(uint16_t(0xABCD));
// Or you can leave the IDs empty and the system will automatically create a
// unique ID for the current machine
// Set the maximum number of domains to 5. Setting 0 means 'unlimited'
writer_qos.data_sharing().set_max_domains(5);
// [OPTIONAL] ThreadSettings for listening thread
writer_qos.data_sharing().data_sharing_listener_thread(eprosima::fastdds::rtps::ThreadSettings{-1, 0, 0, -1});
// Use modified QoS in the creation of the corresponding entity
writer_ = publisher_->create_datawriter(topic_, writer_qos);
3.1.2.2.2 DisablePositiveACKsQosPolicy
此附加 QoS 允许在不需要严格可靠通信且带宽受限的情况下减少网络流量。它通过改变默认行为(即从 reader 向 writer 发送肯定确认)来实现。相反,仅当 reader 丢失样本时才发送否定确认,而 writer 会将数据保留一段可调整的时间,然后才将其视为已确认。参见 DisablePositiveACKsQosPolicy。
QoS 策略数据成员列表:
| Data Member Name | Type | Default Value |
|---|---|---|
enabled |
bool |
false |
duration |
Duration_t |
c_TimeInfinite |
- enabled:指定是否启用此 QoS。如果为 true,则表示肯定确认被禁用,DataReader 仅发送否定确认。否则,肯定确认和否定确认都会被发送。
- duration:规定 DataWriter 在将数据视为已确认之前保留数据的持续时间。此值不适用于 DataReader
此 QoS 策略适用于 DataWriter 和 DataReader 实体。
enabled 数据成员不能在已启用的实体上修改。因此,此功能必须在初始化期间设置。只有 duration 数据成员可以在运行时修改。
为使 DataWriter 和 DataReader 匹配,它们必须遵循兼容性规则。更多详情,请参阅《兼容性规则》。
兼容性规则
为保持 DataReader 和 DataWriter 之间 DisablePositiveACKsQosPolicy 的兼容性,如果 DataWriter 禁用了此 QoS,则 DataReader 不能启用它。
可能的组合如下表所示:
| DataWriter enabled value | DataReader enabled value | Compatibility |
|---|---|---|
true |
true |
Yes |
true |
false |
Yes |
false |
true |
No |
false |
false |
Yes |
示例
// This Qos has different API for DataWriter and DataReader entities, because it is accesed
// through the ReliableWriterQos and ReliableReaderQos respectively.
// For further details see RTPSReliableWriterQos & RTPSReliableReaderQos sections.
DataWriterQos writer_qos;
DataReaderQos reader_qos;
// The DisablePositiveACKsQosPolicy is constructed with enabled = false by default
// Change enabled to true
writer_qos.reliable_writer_qos().disable_positive_acks.enabled = true;
reader_qos.reliable_reader_qos().disable_positive_acks.enabled = true;
// The DisablePositiveACKsQosPolicy is constructed with infinite duration by default
// Change the duration to 1 second
writer_qos.reliable_writer_qos().disable_positive_acks.duration = {1, 0};
reader_qos.reliable_reader_qos().disable_positive_acks.duration = {1, 0};
// Exclusively, DataWriters can additionally disable the heartbeat piggyback
writer_qos.reliable_writer_qos().disable_heartbeat_piggyback = true;
// Use modified QoS in the creation of the corresponding entity
writer_ = publisher_->create_datawriter(topic_, writer_qos);
reader_ = subscriber_->create_datareader(topic_, reader_qos);
3.1.2.2.3 RTPSReliableReaderQos
此 RTPS QoS 策略允许配置 RTPS 可靠读取器的多个方面。参见 RTPSReliableReaderQos。
QoS 策略数据成员列表:
| Data Member Name | Type |
|---|---|
times |
ReaderTimes |
disable_positive_acks |
DisablePositiveACKsQosPolicy |
- times:定义 RTPSReader 事件的持续时间。更多详情,请参阅 ReaderTimes。
- disable_positive_acks:配置禁用肯定确认的设置。更多详情,请参阅 DisablePositiveACKsQosPolicy。
此 QoS 策略适用于 DataReader 实体。
在已启用的实体上,只能修改 DisablePositiveACKsQosPolicy 的 duration 数据成员和 times 数据成员。
ReaderTimes
此结构定义了与可靠读取器事件相关的时间设置。参见 `ReaderTimes`。
结构成员列表:
| Member Name | Type | Default Value |
|---|---|---|
initial_acknack_delay |
Duration_t |
70 ms |
heartbeat_response_delay |
Duration_t |
5 ms |
- initial_acknack_delay:定义初始确认/否定确认(acknack)延迟的持续时间。
- heartbeat_response_delay:设置接收到心跳消息时应用的延迟持续时间。
示例
// This example only applies to DataReader entities
DataReaderQos reader_qos;
// The RTPSReliableReaderQos is constructed with initial_acknack_delay = 70 ms by default
// Change the initialAcknackDelay to 70 nanoseconds
reader_qos.reliable_reader_qos().times.initial_acknack_delay = {0, 70};
// The RTPSReliableReaderQos is constructed with heartbeat_response_delay = 5 ms by default
// Change the heartbeatResponseDelay to 5 nanoseconds
reader_qos.reliable_reader_qos().times.heartbeat_response_delay = {0, 5};
// You can also change the DisablePositiveACKsQosPolicy. For further details see DisablePositiveACKsQosPolicy section.
reader_qos.reliable_reader_qos().disable_positive_acks.enabled = true;
// Use modified QoS in the creation of the DataReader entity
reader_ = subscriber_->create_datareader(topic_, reader_qos);
3.1.2.2.4 RTPSReliableWriterQos
此 RTPS QoS 策略允许配置 RTPS 可靠写入器的多个方面。参见 RTPSReliableWriterQos。
QoS 策略数据成员列表:
| Data Member Name | Type |
|---|---|
times |
WriterTimes |
disable_positive_acks |
DisablePositiveACKsQosPolicy |
disable_heartbeat_piggyback |
DisableHeartbeatPiggyback |
- times:定义 RTPSWriter 事件的持续时间。更多详情,请参阅 WriterTimes。
- disable_positive_acks:配置禁用肯定确认的设置。更多详情,请参阅 DisablePositiveACKsQosPolicy。
- disable_heartbeat_piggyback:配置禁用心跳捎带(heartbeat piggyback)机制的设置。更多详情,请参阅 DisableHeartbeatPiggyback。
此 QoS 策略适用于 DataWriter 实体。
在已启用的实体上,只能修改 DisablePositiveACKsQosPolicy 的 duration 数据成员和 times 数据成员。
WriterTimes
此结构定义了与可靠写入器事件相关的时间设置。
结构成员列表:
| Member Name | Type | Default Value |
|---|---|---|
initial_heartbeat_delay |
Duration_t |
12ms |
heartbeat_period |
Duration_t |
3s |
nack_response_delay |
Duration_t |
5ms |
nack_supression_duration |
Duration_t |
0s |
- initial_heartbeat_delay:定义初始心跳延迟的持续时间。
- heartbeat_period:指定周期性心跳之间的时间间隔。
- nack_response_delay:设置对 ACKNACK 消息的响应所应用的延迟持续时间。
- nack_supression_duration:RTPSWriter 在发送数据后,在持续时间结束之前,会忽略接收到的 nack 消息。
DisableHeartbeatPiggyback
除了使用 heartbeat_period(参见 WriterTimes)定期发送心跳外,可靠的 DataWriter 还会使用一种机制,在向 DataReader 传输数据的同一条消息中附加一个心跳子消息。此机制在特定情况下发挥作用,此时可靠通信状态必须保持最新以维持最佳通信:
- 当 DataWriter 向套接字发送的字节数达到套接字缓冲区长度时,会在最后一个数据后附加一个心跳子消息。
- 当 DataWriter 的历史记录已满时,DataWriter 开始在每个数据后附加心跳子消息。
可以通过此策略禁用该机制。
示例
// This example only applies to DataWriter entities
DataWriterQos writer_qos;
// The RTPSReliableWriterQos is constructed with initial_heartbeat_delay = 12 ms by default
// Change the initial_heartbeat_delay to 20 nanoseconds
writer_qos.reliable_writer_qos().times.initial_heartbeat_delay = {0, 20};
// The RTPSReliableWriterQos is constructed with heartbeat_period = 3 s by default
// Change the heartbeat_period to 5 seconds
writer_qos.reliable_writer_qos().times.heartbeat_period = {5, 0};
// The RTPSReliableWriterQos is constructed with nack_response_delay = 5 ms by default
// Change the nack_response_delay to 10 nanoseconds
writer_qos.reliable_writer_qos().times.nack_response_delay = {0, 10};
// The RTPSReliableWriterQos is constructed with nack_supression_duration = 0 s by default
// Change the nack_supression_duration to 20 nanoseconds
writer_qos.reliable_writer_qos().times.nack_supression_duration = {0, 20};
// You can also change the DisablePositiveACKsQosPolicy. For further details see DisablePositiveACKsQosPolicy section.
writer_qos.reliable_writer_qos().disable_positive_acks.enabled = true;
// The RTPSReliableWriterQos is constructed with disable_heartbeat_piggyback = false by default
// Disable the heartbeat piggyback mechanism.
writer_qos.reliable_writer_qos().disable_heartbeat_piggyback = true;
// Use modified QoS in the creation of the DataWriter entity
writer_ = publisher_->create_datawriter(topic_, writer_qos);
3.1.2.2.5 FlowControllersQos
此 QoS 配置参与者(participant)的流控制器(flow controller)列表,以便稍后在其 DataWriter 上使用。它是一个指向 FlowControllerDescriptor 的共享指针向量,FlowControllerDescriptor 包含以下字段:
| Data Member Name | Type | Default Value |
|---|---|---|
name |
string |
|
scheduler |
FlowControllerSchedulerPolicy |
FIFO_SCHED_POLICY-api| |
max_bytes_per_period |
int32_t |
0 (i.e. infinite) |
period_ms |
uint64_t |
100 |
sender_thread |
ThreadSettings |
更多信息,请参阅《流控制器》部分。
此 QoS 策略适用于 DomainParticipant 实体。
它不能在已启用的实体上更改。
3.1.2.2.6 ParticipantResourceLimitsQos
此 QoS 配置内部资源的分配限制和物理内存的使用。
QoS 策略数据成员列表:
| Data Member Name | Type |
|---|---|
locators |
RemoteLocatorsAllocationAttributes |
participants |
ResourceLimitedContainerConfig |
readers |
ResourceLimitedContainerConfig |
writers |
ResourceLimitedContainerConfig |
send_buffers |
SendBuffersAllocationAttributes |
data_limits |
VariableLengthDataLimits |
content_filter |
ContentFilterProperty::AllocationConfiguration |
- locators:定义远程定位器(locator)集合的限制。
- participants:指定依赖于参与者总数的集合的分配行为和限制。
- readers:指定依赖于每个参与者的读取器总数的集合的分配行为和限制。
- writers:指定依赖于每个参与者的写入器总数的集合的分配行为和限制。
- send_buffers:定义发送缓冲区管理器的分配行为和限制。
- data_limits:规定可变长度数据的限制。
- content_filter:规定内容过滤发现信息的限制。
此 QoS 策略适用于 DomainParticipant 实体。
它不能在已启用的实体上更改。
RemoteLocatorsAllocationAttributes
此结构包含了远程定位器集合的限制。参见 RemoteLocatorsAllocationAttributes。
结构成员列表:
| Member Name | Type | Default Value |
|---|---|---|
max_unicast_locators |
size_t |
4 |
max_multicast_locators |
size_t |
1 |
- max_unicast_locators:此成员控制为每个发现的远程实体保留的单播定位器的最大数量。建议使用同一域内所有系统中找到的本地地址的最大数量。
- max_multicast_locators:此成员控制为每个发现的远程实体保留的多播定位器的最大数量。默认值通常足够,因为每个实体添加多个多播定位器没有意义。
ResourceLimitedContainerConfig
此结构包含资源受限集合的限制以及分配配置,可以是固定大小或动态大小。
结构成员列表:
| Member Name | Type | Default Value |
|---|---|---|
initial |
size_t |
0 |
maximum |
size_t |
std::numeric_limits<size_t>::max() |
increment |
size_t |
1 (dynamic size), 0 (fixed size) |
- initial:指示在集合中预分配的元素数量。
- maximum:指定集合中允许的最大元素数量。
- increment:规定当达到预留容量限制时要添加的项目数量。此成员根据所选的分配配置具有不同的默认值。
SendBuffersAllocationAttributes
此结构包含发送缓冲区分配的限制。参见 SendBuffersAllocationAttributes。
结构成员列表:
| Member Name | Type | Default Value |
|---|---|---|
preallocated_number |
size_t |
0 |
dynamic |
bool |
false |
network_buffers_config |
ResourceLimitedContainerConfig | (16, inf, 16) |
- preallocated_number:此成员控制要分配的初始发送缓冲区数量。默认值将根据可能启动发送操作的线程数,对所需缓冲区数量进行初步估算。
- dynamic:此成员控制缓冲区管理器在发送缓冲区不可用时的行为。当为 true 时,将创建一个新的缓冲区。否则,它将等待缓冲区被返回。
- network_buffers_config:此属性定义每个发送缓冲区中包含的网络缓冲区的分配行为和限制。默认值将预分配 16 个网络缓冲区,并在每次需要增长向量时动态分配 16 个网络缓冲区。
network_buffers_config 也将用于实例化一个 SerializedPayload_t 向量,该向量包含在 RTPS 消息创建期间避免有效负载副本所需的元数据。
VariableLengthDataLimits
此结构包含可变长度数据的限制。参见 VariableLengthDataLimits。
结构成员列表:
| Member Name | Type | Default Value |
|---|---|---|
max_properties |
size_t |
0 |
max_user_data |
size_t |
0 |
max_partitions |
size_t |
0 |
- max_properties:定义本地或远程参与者中属性数据的最大大小(以八位字节为单位)。
- max_user_data:规定本地或远程参与者中用户数据的最大大小(以八位字节为单位)。
- max_partitions:声明本地或远程参与者中分区数据的最大大小(以八位字节为单位)。
ContentFilterProperty::AllocationConfiguration
此结构包含与内容过滤器相关的发现信息的限制。参见 ContentFilterProperty::AllocationConfiguration。
结构成员列表:
| Member Name | Type | Default Value |
|---|---|---|
expression_initial_size |
size_t |
0 |
expression_parameters |
ResourceLimitedContainerConfig | {0, 100, 1} |
- expression_initial_size:过滤器表达式的预分配大小。
- expression_parameters:表达式参数列表的分配配置。
示例
// This example only applies to DomainParticipant entities
DomainParticipantQos participant_qos;
// Set the maximum size of participant resource limits collection to 3 and it allocation configuration to fixed size
participant_qos.allocation().participants =
eprosima::fastdds::ResourceLimitedContainerConfig::fixed_size_configuration(
3u);
// Set the maximum size of reader's resource limits collection to 2 and its allocation configuration to fixed size
participant_qos.allocation().readers =
eprosima::fastdds::ResourceLimitedContainerConfig::fixed_size_configuration(2u);
// Set the maximum size of writer's resource limits collection to 1 and its allocation configuration to fixed size
participant_qos.allocation().writers =
eprosima::fastdds::ResourceLimitedContainerConfig::fixed_size_configuration(1u);
// Set the maximum size of the partition data to 256
participant_qos.allocation().data_limits.max_partitions = 256u;
// Set the maximum size of the user data to 256
participant_qos.allocation().data_limits.max_user_data = 256u;
// Set the maximum size of the properties data to 512
participant_qos.allocation().data_limits.max_properties = 512u;
// Set the preallocated filter expression size to 512
participant_qos.allocation().content_filter.expression_initial_size = 512u;
// Set the maximum number of expression parameters to 4 and its allocation configuration to fixed size
participant_qos.allocation().content_filter.expression_parameters =
eprosima::fastdds::ResourceLimitedContainerConfig::fixed_size_configuration(4u);
// Use modified QoS in the creation of the corresponding DomainParticipant
participant_ = factory_->create_participant(domain, participant_qos);
3.1.2.2.7 PropertyPolicyQos
此附加的 QoS 策略(PropertyPolicyQos)用于存储名称/值对,可用于配置某些无法通过标准 QoS 策略直接配置的 DDS 设置。有关可使用此 QoS 策略配置的设置的完整列表,请参阅 PropertyPolicyQos 选项。
此 QoS 还允许添加自定义的用户属性,这些属性可以发送给外部实体。这可以通过将属性的 propagate 值设置为 true 来实现。
此 QoS 策略适用于 DomainParticipant、DataWriter 和 DataReader 实体。
它不能在已启用的实体上更改。
示例
// This example uses a DataWriter, but it can also be applied to DomainParticipant and DataReader entities
DataWriterQos writer_qos;
// Add new property for the Auth:PKI-DH plugin
writer_qos.properties().properties().emplace_back("dds.sec.auth.plugin", "builtin.PKI-DH");
// Add new property for the Access:Permissions plugin
writer_qos.properties().properties().emplace_back(eprosima::fastdds::rtps::Property("dds.sec.access.plugin",
"builtin.Access-Permissions"));
// Add new user custom property to send to external Participants
writer_qos.properties().properties().emplace_back("Custom Property Name", "Custom value", true);
// Use modified QoS in the creation of the corresponding entity
writer_ = publisher_->create_datawriter(topic_, writer_qos);
3.1.2.2.8 PublishModeQosPolicy
此 QoS 策略配置 DataWriter 发送数据的方式。参见 PublishModeQosPolicy。
它还配置了使用异步发布时要使用的流控制器的名称。它应该是创建 DomainParticipant 时注册的流控制器的名称。参见 FlowControllersQos。
QoS 策略数据成员列表:
| Data Member Name | Type | Default Value |
|---|---|---|
kind |
PublishModeQosPolicyKind | SYNCHRONOUS_PUBLISH_MODE |
flow_controller_name |
string |
FASTDDS_FLOW_CONTROLLER_DEFAULT |
此 QoS 策略适用于 DataWriter 实体。
它不能在已启用的实体上更改。
PublishModeQosPolicyKind
有两种可能的取值(参见 PublishModeQosPolicyKind):
- SYNCHRONOUS_PUBLISH_MODE:数据在调用写入操作的用户线程上下文中发送。
- ASYNCHRONOUS_PUBLISH_MODE:由内部线程负责异步发送数据。写入操作在实际发送数据之前返回。
此外,flow_controller_name 必须设置为有效的流控制器描述符名称。
示例
// This example only applies to DataWriter entities
DataWriterQos writer_qos;
// The PublishModeQosPolicy is constructed with kind = SYNCHRONOUS by default
// Change the kind to ASYNCHRONOUS
writer_qos.publish_mode().kind = ASYNCHRONOUS_PUBLISH_MODE;
// Use modified QoS in the creation of the DataWriter entity
writer_ = publisher_->create_datawriter(topic_, writer_qos);
3.1.2.2.9 ReaderResourceLimitsQos
此 QoS 策略根据将与 DataReader 匹配的 DataWriter 的最大数量,规定了匹配的 DataWriter 的资源受限集合的限制。参见 ReaderResourceLimitsQos。
QoS 策略数据成员列表:
| Data Member Name | Type |
|---|---|
matched_publisher_allocation |
ResourceLimitedContainerConfig |
此 QoS 策略适用于 DataReader 实体。
它不能在已启用的实体上更改。
示例
// This example only applies to DataReader entities
DataReaderQos reader_qos;
// Set the maximum size for writer matched resource limits collection to 1 and its allocation configuration to fixed size
reader_qos.reader_resource_limits().matched_publisher_allocation =
eprosima::fastdds::ResourceLimitedContainerConfig::fixed_size_configuration(1u);
// Set the maximum size for sample info resource limits to 22 and its allocation configuration to fixed size
reader_qos.reader_resource_limits().sample_infos_allocation =
eprosima::fastdds::ResourceLimitedContainerConfig::fixed_size_configuration(22u);
// Set the maximum size for writer matched resource limits collection to 3 and its allocation configuration to fixed size
reader_qos.reader_resource_limits().outstanding_reads_allocation =
eprosima::fastdds::ResourceLimitedContainerConfig::fixed_size_configuration(3u);
reader_qos.reader_resource_limits().max_samples_per_read = 42;
// Use modified QoS in the creation of the DataReader entity
reader_ = subscriber_->create_datareader(topic_, reader_qos);
3.1.2.2.10 WriterResourceLimitsQos
此 QoS 策略根据将与 DataWriter 匹配的 DataReader 的最大数量,规定了匹配的 DataReader 的资源受限集合的限制。参见 WriterResourceLimitsQos。
QoS 策略数据成员列表:
| Data Member Name | Type |
|---|---|
matched_subscriber_allocation |
ResourceLimitedContainerConfig |
reader_filters_allocation |
ResourceLimitedContainerConfig |
此 QoS 策略适用于 DataWriter 实体。
它不能在已启用的实体上更改。
示例
// This example only applies to DataWriter entities
DataWriterQos writer_qos;
// Set the maximum size for reader matched resource limits collection to 3 and its allocation configuration to fixed size
writer_qos.writer_resource_limits().matched_subscriber_allocation =
eprosima::fastdds::ResourceLimitedContainerConfig::fixed_size_configuration(3u);
// Set the maximum number of writer side content filters to 1 and its allocation configuration to fixed size
writer_qos.writer_resource_limits().reader_filters_allocation =
eprosima::fastdds::ResourceLimitedContainerConfig::fixed_size_configuration(1u);
// Use modified QoS in the creation of the DataWriter entity
writer_ = publisher_->create_datawriter(topic_, writer_qos);
3.1.2.2.11 RTPSEndpointQos
此 QoS 策略配置 RTPS 端点的各个方面,例如定位器列表、标识符和历史内存策略。参见 RTPSEndpointQos。
QoS 策略数据成员列表:
| Data Member Name | Type | Default Value |
|---|---|---|
unicast_locator_list |
LocatorList |
Empty List |
multicast_locator_list |
LocatorList |
Empty List |
remote_locator_list |
LocatorList |
Empty List |
external_unicast_locators |
ExternalLocators |
Empty |
ignore_non_matching_locators |
bool |
false |
user_defined_id |
int16_t |
-1 |
entity_id |
int16_t |
-1 |
history_memory_policy |
MemoryManagementPolicy | PREALLOCATED_WITH_REALLOC_MEMORY_MODE |
- unicast_locator_list:定义与 DDS 实体关联的单播定位器列表。DataReader 和 DataWriter 继承在 DomainParticipant 中设置的单播定位器列表,但可以通过此 QoS 进行更改。
- multicast_locator_list:存储与 DDS 实体关联的多播定位器列表。默认情况下,DataReader 和 DataWriter 不使用任何多播定位器,但可以通过此 QoS 进行更改。
- remote_locator_list:声明与 DDS 实体关联的远程定位器列表。
- external_unicast_locators:定义用于与此 DDS 实体通信时要通告的外部定位器。
- ignore_non_matching_locators:定义当从其他 DDS 实体收到的通告中的定位器与此 DDS 实体通告的任何定位器都不匹配时,是否忽略这些定位器。
- user_defined_id:建立用于静态端点发现的唯一标识符。
- entity_id:用户可以为端点指定标识符。
- history_memory_policy:指示在处理 CacheChange 时内存的管理方式。
此 QoS 策略适用于 DataWriter 和 DataReader 实体。
它不能在已启用的实体上更改。
MemoryManagementPolicy
有四种可能的取值(参见 MemoryManagementPolicy):
- PREALLOCATED_MEMORY_MODE:此选项将大小设置为每种数据类型的最大值。它会产生最大的内存占用,但分配次数最少。
- PREALLOCATED_WITH_REALLOC_MEMORY_MODE:此选项将大小设置为每种数据类型的默认值,并在收到更大的消息时需要重新分配。它以增加分配次数为代价,产生较低的内存占用。
- DYNAMIC_RESERVE_MEMORY_MODE:此选项在消息到达时动态分配大小。它产生的内存占用最少,但分配次数最高。
- DYNAMIC_REUSABLE_MEMORY_MODE:此选项类似于 DYNAMIC_RESERVE_MEMORY_MODE,但分配的内存会为将来的消息重复使用。
示例
// This example uses a DataWriter, but it can also be applied to DataReader entities
DataWriterQos writer_qos;
// Add new unicast locator with port 7800
eprosima::fastdds::rtps::Locator_t new_unicast_locator;
new_unicast_locator.port = 7800;
writer_qos.endpoint().unicast_locator_list.push_back(new_unicast_locator);
// Add new multicast locator with IP 239.255.0.4 and port 7900
eprosima::fastdds::rtps::Locator_t new_multicast_locator;
eprosima::fastdds::rtps::IPLocator::setIPv4(new_multicast_locator, "239.255.0.4");
new_multicast_locator.port = 7900;
writer_qos.endpoint().multicast_locator_list.push_back(new_multicast_locator);
// Add an external locator with IP 100.100.100.10, port 12345, mask 24, externality 1, and cost 0
eprosima::fastdds::rtps::LocatorWithMask external_locator;
external_locator.kind = LOCATOR_KIND_UDPv4;
external_locator.port = 12345;
external_locator.mask(24);
writer_qos.endpoint().external_unicast_locators[1][0].push_back(external_locator);
// Drop non matching locators
writer_qos.endpoint().ignore_non_matching_locators = true;
// Set 3 as user defined id
writer_qos.endpoint().user_defined_id = 3;
// Set 4 as entity id
writer_qos.endpoint().entity_id = 4;
// The RTPSWriterQos is constructed with history_memory_policy = PREALLOCATED by default
// Change the history_memory_policy to DYNAMIC_RESERVE
writer_qos.endpoint().history_memory_policy = eprosima::fastdds::rtps::DYNAMIC_RESERVE_MEMORY_MODE;
// Use modified QoS in the creation of the corresponding entity
writer_ = publisher_->create_datawriter(topic_, writer_qos);
3.1.2.2.12 ThreadSettings
此结构是其他 QoS 策略的一部分,允许控制所创建线程的某些操作系统设置。默认值将在创建的线程上保留操作系统的默认设置。更改这些值可能需要特殊权限。
| Data Member Name | Type | Default Value |
|---|---|---|
scheduling_policy |
int32_t |
-1 |
priority |
int32_t |
-2^31 |
affinity |
uint32_t |
0 |
stack_size |
int32_t |
-1 |
- scheduling_policy:配置线程使用的调度策略。此值特定于平台,并按原样用于配置特定平台的线程。在 Windows 平台上被忽略。
- priority:配置线程的优先级。此值特定于平台,并按原样用于配置特定平台的线程。
- affinity:在某些系统(Windows、Linux)上,这是一个位掩码,用于将线程亲和性单独设置到每个核心。在 MacOS 上,这设置线程的亲和性标签,操作系统尝试在具有相同亲和性的线程之间共享 L2 缓存。此值特定于平台,并按原样用于配置特定平台的线程。
- stack_size:以字节为单位配置线程的栈大小。此值特定于平台,并按原样用于配置特定平台的线程。
基于端口的传输描述符中接收线程的 ThreadSettings 也可以通过将每个特定于线程的配置与其对应的端口号关联来进行配置。
示例
以下示例说明了线程设置配置:
// This example uses a specific thread of the DomainParticipantQos, but it can also be applied to most of
// the threads used by FastDDS in DomainParticipantFactoryQos, DomainParticipantQos or DataSharingQosPolicy.
// Each thread has its own getter and setter function. See Fast DDS documentation for further details.
DomainParticipantQos participant_qos;
participant_qos.timed_events_thread().scheduling_policy = 2;
participant_qos.timed_events_thread().priority = 10;
participant_qos.timed_events_thread().affinity = 4;
participant_qos.timed_events_thread().stack_size = 2000;
// Use modified QoS in the creation of the corresponding entity
participant_ = factory_->create_participant(domain, participant_qos);
接下来的示例描绘了接收线程设置配置:
// Implement a Custom class, derived from PortBasedTransportDescriptor, to set the reception threads configuration
CustomPortBasedTransportDescriptor descriptor;
PortBasedTransportDescriptor::ReceptionThreadsConfigMap reception_threads_config;
reception_threads_config[20000].scheduling_policy = 1;
reception_threads_config[20000].priority = 30;
reception_threads_config[20000].affinity = 2;
reception_threads_config[20000].stack_size = 1024;
reception_threads_config[20001].scheduling_policy = 2;
reception_threads_config[20001].priority = 10;
reception_threads_config[20001].affinity = 6;
reception_threads_config[20001].stack_size = 4096;
// Use setter to set the reception threads configuration
descriptor.reception_threads(reception_threads_config);
3.1.2.2.13 TransportConfigQos
此 QoS 策略允许配置传输层设置。参见 TransportConfigQos。
QoS 策略数据成员列表:
| Data Member Name | Type | Default Value |
|---|---|---|
user_transports |
std::vector<std::shared_ptr<TransportDescriptorInterface>> |
Empty vector |
use_builtin_transports |
bool |
true |
send_socket_buffer_size |
uint32_t |
0 |
listen_socket_buffer_size |
uint32_t |
0 |
builtin_transports_reception_threads() |
ThreadSettings | |
max_msg_size_no_frag |
uint32_t |
0 |
netmask_filter |
fastdds::rtps::NetmaskFilterKind |
- user_transports:此数据成员定义要使用的传输列表,可以与内置传输一起使用或替代内置传输。
- use_builtin_transports:它控制是否启用或禁用内置传输层。如果设置为 false,则默认的 UDPv4 实现将被禁用。
- send_socket_buffer_size:默认情况下,Fast DDS 使用系统默认大小创建套接字缓冲区。此数据成员允许更改用于发送数据的发送套接字缓冲区大小。
- listen_socket_buffer_size:监听套接字缓冲区大小也使用系统默认大小创建,但可以使用此数据成员进行更改。
- builtin_transports_reception_threads():内置传输接收线程的 ThreadSettings。
- max_msg_size_no_frag:用于避免分片的最大消息大小。当配置的传输允许发送大数据报(例如 SHM 或 TCP)时非常有用。
- netmask_filter:网络过滤器配置。
此 QoS 策略适用于 DomainParticipant 实体。
它不能在已启用的实体上更改。
TransportDescriptorInterface
此结构是用于定义传输配置的数据类型的基础。
结构成员列表:
| Member Name | Type |
|---|---|
maxMessageSize |
uint32_t |
maxInitialPeersRange |
uint32_t |
- maxMessageSize:此成员设置传输消息缓冲区的最大大小(以字节为单位)。
- maxInitialPeersRange:此成员声明要尝试连接的最大猜测初始对等点数。
示例
// This example only applies to DomainParticipant entities
DomainParticipantQos participant_qos;
// Add new transport to the list of user transports
std::shared_ptr<eprosima::fastdds::rtps::UDPv4TransportDescriptor> descriptor =
std::make_shared<eprosima::fastdds::rtps::UDPv4TransportDescriptor>();
descriptor->sendBufferSize = 9126;
descriptor->receiveBufferSize = 9126;
participant_qos.transport().user_transports.push_back(descriptor);
// Set use_builtin_transports to false
participant_qos.transport().use_builtin_transports = false;
// [OPTIONAL] Set ThreadSettings for the builtin transports reception threads
participant_qos.transport().builtin_transports_reception_threads_ =
eprosima::fastdds::rtps::ThreadSettings{2, 2, 2, 2};
// Set max_msg_size_no_frag to a value > 65500 KB
participant_qos.transport().max_msg_size_no_frag = 70000;
// Configure netmask filter
participant_qos.transport().netmask_filter = eprosima::fastdds::rtps::NetmaskFilterKind::ON;
// Use modified QoS in the creation of the DomainParticipant entity
participant_ = factory_->create_participant(domain, participant_qos);
TransportConfigQos 也可以通过选择可用的内置传输选项之一来修改内置传输配置。参见《管理内置传输》或 setup_transports()。
3.1.2.2.14 WireProtocolConfigQos
此 QoS 策略允许配置线路协议。
QoS 策略数据成员列表:
| Data Member Name | Type | Default Value |
|---|---|---|
prefix |
GuidPrefix_t |
0 |
participant_id |
int32_t |
-1 |
builtin |
BuiltinAttributes |
|
port |
PortParameters |
|
default_unicast_locator_list |
LocatorList |
Empty List |
default_multicast_locator_list |
LocatorList |
Empty List |
default_external_unicast_locators |
ExternalLocators |
Empty |
ignore_non_matching_locators |
bool |
false |
QoS 策略方法列表:
| Method name | Input parameters | Return type | Description |
|---|---|---|---|
easy_mode() |
std::string ip |
ReturnCode_t |
Setter for easy_mode_ip_ private member. |
easy_mode() |
Empty | std::string |
Getter for easy_mode_ip_ private member. |
- prefix:此数据成员允许用户手动设置 GUID 前缀。
- participant_id:设置参与者标识符。默认情况下,它将由域自动生成。
- builtin:此数据成员允许配置内置参数。
- port:此数据成员允许配置端口参数以及与 RTPS 协议相关的增益(公认端口)。
- default_unicast_locator_list:声明在 RTPSParticipant 内部定义的任何端点(如果定义时未指定单播定位器)要使用的默认单播定位器列表。此列表应至少包含一个定位器。
- default_multicast_locator_list:存储在 RTPSParticipant 内部定义的任何端点(如果定义时未指定多播定位器)要使用的默认多播定位器列表。此列表通常为空。
- default_external_unicast_locators:定义在参与者内部定义的任何端点(如果定义时未指定单播定位器)要使用的外部定位器。
- ignore_non_matching_locators:定义当从其他 DDS 参与者收到的通告中的定位器与此 DDS 参与者通告的任何定位器都不匹配时,是否忽略这些定位器。
- easy_mode():此方法允许用户设置或获取 easy_mode_ip_ 私有成员,该成员存储发现服务器简易模式配置中要使用的 IP 地址。当调用 easy_mode() 设置器时,输入的字符串参数会被验证以确保它是有效的 IPv4 地址。如果不是,easy_mode_ip_ 将被设置为空字符串,表示 ROS 2 简易模式被禁用。
如果简易模式发现服务器的 IP 地址同时通过 ROS2_EASY_MODE 环境变量以及手动通过 XML 或 WireProtocolConfigQos 进行了配置,则手动配置的值优先,从而忽略环境变量的值。
此 QoS 策略适用于 DomainParticipant 实体。
在已启用的实体上,唯一可变的字段是 m_DiscoveryServers,它包含在 builtin 的 discovery_config 中(参见《在运行时修改远程服务器列表》)。
在部署中,如果在同一主机内创建多个 DomainParticipant,当创建的 DomainParticipant 数量达到 BuiltinAttributes::mutation_tries 的值(默认为 100)时,可能会导致它们无法获得可用端口。当发生这种情况时,DomainParticipant 将无法创建监听端口(这会在日志中发出警告),并且将在没有配置单播定位器的情况下创建。
示例
// This example only applies to DomainParticipant entities
DomainParticipantQos participant_qos;
// Set the guid prefix
std::istringstream("72.61.73.70.66.61.72.6d.74.65.73.74") >> participant_qos.wire_protocol().prefix;
// Manually set the participantId
participant_qos.wire_protocol().participant_id = 11;
// Configure Builtin Attributes
participant_qos.wire_protocol().builtin.discovery_config.discoveryProtocol =
eprosima::fastdds::rtps::DiscoveryProtocol::SERVER;
// Add locator to unicast list
eprosima::fastdds::rtps::Locator_t server_locator;
eprosima::fastdds::rtps::IPLocator::setIPv4(server_locator, "192.168.10.57");
server_locator.port = 56542;
participant_qos.wire_protocol().builtin.metatrafficUnicastLocatorList.push_back(server_locator);
// Add a metatraffic external locator with IP 100.100.100.10, port 34567, mask 24, externality 1, and cost 0
eprosima::fastdds::rtps::LocatorWithMask meta_external_locator;
meta_external_locator.kind = LOCATOR_KIND_UDPv4;
meta_external_locator.port = 34567;
meta_external_locator.mask(24);
participant_qos.wire_protocol().builtin.metatraffic_external_unicast_locators[1][0].push_back(
meta_external_locator);
// Add locator to default unicast locator list
eprosima::fastdds::rtps::Locator_t unicast_locator;
eprosima::fastdds::rtps::IPLocator::setIPv4(unicast_locator, 192, 168, 1, 41);
unicast_locator.port = 7400;
participant_qos.wire_protocol().default_unicast_locator_list.push_back(unicast_locator);
// Add locator to default multicast locator list
eprosima::fastdds::rtps::Locator_t multicast_locator;
eprosima::fastdds::rtps::IPLocator::setIPv4(multicast_locator, 192, 168, 1, 41);
multicast_locator.port = 7400;
participant_qos.wire_protocol().default_multicast_locator_list.push_back(multicast_locator);
// Add a default external locator with IP 100.100.100.10, port 23456, mask 24, externality 1, and cost 0
eprosima::fastdds::rtps::LocatorWithMask external_locator;
external_locator.kind = LOCATOR_KIND_UDPv4;
external_locator.port = 23456;
external_locator.mask(24);
participant_qos.wire_protocol().default_external_unicast_locators[1][0].push_back(external_locator);
// Drop non matching locators
participant_qos.wire_protocol().ignore_non_matching_locators = true;
// Configure the ROS 2 Easy Mode master Discovery Server IP
participant_qos.wire_protocol().easy_mode("127.0.0.1");
// Increase mutation tries
participant_qos.wire_protocol().builtin.mutation_tries = 300u;
// Use a specific flow controller to control the builtin writers
participant_qos.wire_protocol().builtin.flow_controller_name = "AlreadyExistingFlowController";
// Use modified QoS in the creation of the DomainParticipant entity
participant_ = factory_->create_participant(domain, participant_qos);
有关扩展的 XML 信息,请参阅 DomainParticipant 配置和内置参数的 XML 部分。
3.1.2.3 XTypes Extensions
本节将解释 XTypes 规范中定义的 QoS 策略扩展:
3.1.2.3.1 DataRepresentationQosPolicy
此 XTypes QoS 策略规定了 DataWriter 和 DataReader 将使用哪些数据表示形式。
DataWriter 提供单一的数据表示形式,用于与匹配的 DataReader 进行通信。DataReader 可以请求一种或多种数据表示形式,为了与 DataWriter 建立通信,DataWriter 提供的数据表示形式必须包含在 DataReader 的请求中。参见 DataRepresentationQosPolicy。
QoS 策略数据成员列表:
| Data Member Name | Type | Default Value | DataReader default value | DataWriter default value | Topic default value |
|---|---|---|---|---|---|
m_value |
std::vector<DataRepresentationId> | Empty vector | [XCDR_DATA_REPRESENTATION, XCDR2_DATA_REPRESENTATION] |
[XCDR2_DATA_REPRESENTATION] |
[XCDR_DATA_REPRESENTATION] |
此 QoS 策略适用于 Topic、DataReader 和 DataWriter 实体。
它不能在已启用的实体上更改。
DataRepresentationId
有三种可能的取值(参见 DataRepresentationId):
- XCDR_DATA_REPRESENTATION:此选项对应于第一版扩展 CDR 表示编码。
- XML_DATA_REPRESENTATION:此选项对应于 XML 数据表示。
- XCDR2_DATA_REPRESENTATION:此选项对应于第二版扩展 CDR 表示编码。
示例
// This example uses a DataWriter, but it can also be applied to Topic entities.
// DataRepresentationQosPolicy of DataReaders is contained in the TypeConsistencyQos
// (for further details see TypeConsistencyQos section).
DataWriterQos writer_qos;
// Add XCDR v1 data representation to the list of valid representations
writer_qos.representation().m_value.push_back(DataRepresentationId_t::XCDR_DATA_REPRESENTATION);
// Add XML data representation to the list of valid representations
writer_qos.representation().m_value.push_back(DataRepresentationId_t::XML_DATA_REPRESENTATION);
// Use modified QoS in the creation of the corresponding entity
writer_ = publisher_->create_datawriter(topic_, writer_qos);
XML
此 QoS 策略目前无法使用 XML 进行配置。
3.1.2.3.2 TypeConsistencyEnforcementQosPolicy
此 QoS 策略将在未来版本中实现。
此 XTypes QoS 策略扩展定义了用于确定 DataWriter 中使用的数据类型是否与 DataReader 中使用的数据类型一致的规则。参见 TypeConsistencyEnforcementQosPolicy。
QoS 策略数据成员列表:
| Data Member Name | Type | Default Value |
|---|---|---|
m_kind |
TypeConsistencyKind | ALLOW_TYPE_COERCION |
m_ignore_sequence_bounds |
bool |
true |
m_ignore_string_bounds |
bool |
true |
m_ignore_member_names |
bool |
true |
m_prevent_type_widening |
bool |
true |
m_force_type_validation |
bool |
true |
- m_kind:它确定 DataWriter 中的类型是否必须与 DataReader 中的类型相等。更多详情,请参阅 TypeConsistencyKind。
- m_ignore_sequence_bounds:此数据成员控制序列边界是否纳入类型可分配性考虑。如果其值为 true,则不考虑序列的最大长度,这意味着长度为 L2 的序列 T2 将可以分配给长度为 L1 的序列 T1,即使 L2 大于 L1。但如果为 false,则 L1 必须大于或等于 L2,才能认为序列可分配。
- m_ignore_string_bounds:它控制字符串边界是否纳入类型分配考虑。如果其值为 true,则不考虑字符串的最大长度,这意味着长度为 L2 的字符串 S2 将可以分配给长度为 L1 的字符串 S1,即使 L2 大于 L1。但如果为 false,则 L1 必须大于或等于 L2,才能认为字符串可分配。
- m_ignore_member_names:此布尔值控制成员名称是否纳入类型可分配性考虑。如果为 true,则除了成员 ID 外,成员名称也被视为可分配性的一部分,这意味着具有相同 ID 的成员也必须具有相同的名称。但如果值为 false,则成员名称被忽略。
- m_prevent_type_widening:此数据成员控制是否允许类型拓宽。如果为 false,则允许类型拓宽;但如果为 true,则更宽的类型不能分配给更窄的类型。
- m_force_type_validation:它控制服务是否需要类型信息来完成 DataWriter 和 DataReader 之间的匹配。如果启用,则必须具有完整类型信息;否则,不是必需的。
此 QoS 策略适用于 DataReader 实体。
它不能在已启用的实体上更改。
TypeConsistencyKind
有两种可能的取值(TypeConsistencyKind):
- DISALLOW_TYPE_COERCION:DataWriter 和 DataReader 必须支持相同的数据类型才能进行通信。
- ALLOW_TYPE_COERCION:DataWriter 和 DataReader 不需要支持相同的数据类型即可通信,前提是 DataReader 的类型可以从 DataWriter 的类型分配。
3.1.3 Status(状态)
每个实体都与一组状态对象相关联,这些对象的值代表了该实体的通信状态。状态值的变化是由与每个实体相关的通信事件引起的,例如,当新数据到达、发现新参与者或远程端点丢失时。状态被分解为多个状态对象,每个对象涉及通信的不同方面,以便这些状态对象中的每一个都可以独立于其他对象而变化。
状态对象的变化会触发相应的监听器回调,从而允许实体将事件通知给应用程序。对于名为 fooStatus 的给定状态对象,实体监听器接口定义了一个回调函数 on_foo(),该函数将在状态发生变化时被调用。请注意,某些状态的数据成员会在每次调用相应的监听器时被重置。此规则的唯一例外是当实体没有附加监听器时,因此无法调用回调。详情请参阅每个状态的文档。
条件和等待集(Wait-sets)通过 StatusCondition 为应用程序提供了一种替代机制,使其能够感知状态对象的变化。此机制的优点在于,应用程序可以同时等待多个实体的变化。它还有助于提高系统的确定性,因为通知不是在内部线程上处理的,而使用监听器时则是在内部线程上处理的。
实体暴露了访问其状态值的函数。对于名为 fooStatus 的给定状态,实体暴露了一个成员函数 get_foo() 来访问其 fooStatus 中的数据。唯一的例外是 DataOnReaders 和 DataAvailable。这些获取器函数返回一个只读结构体,其中所有数据成员都是公共的,应用程序可以访问。请注意,某些状态的数据成员会在应用程序每次调用获取器函数时被重置。详情请参阅每个状态的文档。
以下小节将描述每个状态对象、其数据成员以及它们适用于哪种实体类型。下表提供了快速参考以及每个状态在 StatusMask 中的对应位。
| Status Name | Entity | Listener callback | Accessor | Bit |
|---|---|---|---|---|
| InconsistentTopicStatus | Topic | on_inconsistent_topic() |
get_inconsistent_topic_status() |
0 |
| OfferedDeadlineMissedStatus | DataWriter | on_offered_deadline_missed() |
get_offered_deadline_missed_status() |
1 |
| RequestedDeadlineMissedStatus | DataReader | on_requested_deadline_missed() |
get_requested_deadline_missed_status() |
2 |
| OfferedIncompatibleQosStatus | DataWriter | on_offered_incompatible_qos() |
get_offered_incompatible_qos_status() |
5 |
| RequestedIncompatibleQosStatus | DataReader | on_requested_incompatible_qos() |
get_requested_incompatible_qos_status() |
6 |
| SampleLostStatus | DataReader | on_sample_lost() |
get_sample_lost_status() |
7 |
| SampleRejectedStatus | DataReader | on_sample_rejected() |
get_sample_rejected_status() |
8 |
| DataOnReaders | Subscriber | on_data_on_readers() |
N/A | 9 |
| DataAvailable | DataReader | on_data_available() |
N/A | 10 |
| LivelinessLostStatus | DataWriter | on_liveliness_lost() |
get_liveliness_lost_status() |
11 |
| LivelinessChangedStatus | DataReader | on_liveliness_changed() |
get_liveliness_changed_status() |
12 |
| PublicationMatchedStatus | DataWriter | on_publication_matched() |
get_publication_matched_status() |
13 |
| SubscriptionMatchedStatus | DataReader | on_subscription_matched() |
get_subscription_matched_status() |
14 |
3.1.3.1 InconsistentTopicStatus
每当发现不一致的远程主题时,此状态都会发生变化,即发现具有相同名称但特性与当前主题不同的主题。参见 InconsistentTopicStatus。
状态数据成员列表:
| Data Member Name | Type |
|---|---|
total_count |
int32_t |
total_count_change |
int32_t |
- total_count:自当前主题创建以来发现的不一致主题的累计总数。
- total_count_change:自上次调用 on_inconsistent_topic() 或读取状态以来,total_count 的变化量。
当前不支持此状态,将在未来版本中实现。因此,尝试访问此状态将返回 NOT_SUPPORTED,并且相应的监听器将永远不会被调用。
3.1.3.2 DataOnReaders
每当属于当前订阅者的任何 DataReader 上有新数据可供应用程序使用时,此状态变为活动状态。没有获取器函数可以访问此状态,因为它不跟踪与数据本身相关的任何信息。其唯一目的是触发附加到 DataReader 的监听器上的 on_data_on_readers() 回调。
3.1.3.3 DataAvailable
每当 DataReader 上有新数据可供应用程序使用时,此状态变为活动状态。没有获取器函数可以访问此状态,因为它不跟踪与数据本身相关的任何信息。其唯一目的是触发附加到 DataReader 的监听器上的 on_data_available() 回调。
3.1.3.4 LivelinessChangedStatus
每当匹配的 DataWriter 的活性状态发生变化时,此状态都会发生变化。可能是因为处于非活动状态的 DataWriter 变为活动状态,或者反之亦然。参见 LivelinessChangedStatus。
状态数据成员列表:
| Data Member Name | Type |
|---|---|
alive_count |
int32_t |
not_alive_count |
int32_t |
alive_count_change |
int32_t |
not_alive_count_change |
int32_t |
last_publication_handle |
InstanceHandle_t |
- alive_count:当前活跃的 DataWriter 总数。每当新匹配的 DataWriter 断言其活性,或被视为非存活的 DataWriter 重新断言其活性时,此计数增加。每当活跃的 DataWriter 变为非存活(无论是由于未能断言其活性,还是因任何原因被删除)时,此计数减少。
- not_alive_count:当前被视为非存活的匹配 DataWriter 总数。每当活跃的 DataWriter 因未能断言其活性而变为非存活时,此计数增加。每当被视为非存活的 DataWriter 重新断言其活性时,此计数减少。DataWriter 的正常匹配和取消匹配不影响此计数。
- alive_count_change:自上次调用 on_liveliness_changed() 或读取状态以来,alive_count 的变化量。可以是正值或负值。
- not_alive_count_change:自上次调用 on_liveliness_changed() 或读取状态以来,not_alive_count 的变化量。可以是正值或负值。
- last_publication_handle:最后一个活性状态发生变化的 DataWriter 的句柄。如果从未发生过活性变化,其值为 c_InstanceHandle_Unknown。
3.1.3.5 RequestedDeadlineMissedStatus
每当 DataReader 在其 DataReaderQos 配置的截止期限内未收到数据时,此状态都会发生变化。参见 RequestedDeadlineMissedStatus。
状态数据成员列表:
| Data Member Name | Type |
|---|---|
total_count |
int32_t |
total_count_change |
int32_t |
last_instance_handle |
InstanceHandle_t |
- total_count:当前 DataReader 读取的任何实例错过截止时间的累计总数。由于截止期限独立应用于主题的每个实例,因此对于在截止期限内未收到数据的每个实例,计数将增加一。
- total_count_change:自上次调用 on_requested_deadline_missed() 或读取状态以来,total_count 的变化量。其值只能为零或正数。
- last_instance_handle:最后一个错过截止时间的实例的句柄。如果从未错过截止时间,其值为 c_InstanceHandle_Unknown。
3.1.3.6 RequestedIncompatibleQosStatus
每当 DataReader 发现一个 DataWriter,其主题匹配且具有公共分区,但 QoS 配置与 DataReader 上定义的配置不兼容时,此状态都会发生变化。参见 RequestedIncompatibleQosStatus。
状态数据成员列表:
| Data Member Name | Type |
|---|---|
total_count |
int32_t |
total_count_change |
int32_t |
last_policy_id |
QosPolicyId_t |
policies |
QosPolicyCountSeq |
- total_count:累计总数,即发现匹配主题且具有公共分区,但 QoS 配置与 DataReader 上定义的配置不兼容的 DataWriter 数量。
- total_count_change:自上次调用 on_requested_incompatible_qos() 或读取状态以来,total_count 的变化量。其值只能为零或正数。
- last_policy_id:被发现与当前 DataReader 不兼容的某个策略的策略 ID。如果多个策略碰巧不兼容,则此成员中只报告其中一个。
- policies:一个集合,为每个策略保存该策略被发现与匹配主题且具有公共分区的远程 DataWriter 所提供的策略不兼容的总次数。有关每个策略存储的更多信息,请参见 QosPolicyCountSeq 和 QosPolicyCount。
3.1.3.6.1 QosPolicyCountSeq
为每个策略(Policy)持有一个 QosPolicyCount,按其 QosPolicyId_t 索引。因此,ID 为 N 的 QoS 策略将位于序列中的第 N 个位置。参见 QosPolicyCountSeq。
DataReader* reader_ =
subscriber_->create_datareader(topic_, DATAREADER_QOS_DEFAULT);
// Get how many times ReliabilityQosPolicy was not compatible with a remote writer
RequestedIncompatibleQosStatus status;
reader_->get_requested_incompatible_qos_status(status);
uint32_t incompatible_reliability_count = status.policies[RELIABILITY_QOS_POLICY_ID].count;
3.1.3.6.2 QosPolicyCount
此结构为一个策略保存一个计数器。参见 QosPolicyCount。
数据成员列表:
| Data Member Name | Type |
|---|---|
policy_id |
QosPolicyId_t |
count |
int32_t |
- policy_id:策略的 ID。
- count:该策略的计数器值。
3.1.3.7 SampleLostStatus
每当有新的数据样本丢失且永远无法接收时,此状态都会发生变化。参见 SampleLostStatus。
根据可靠性(reliability())的不同,判定样本丢失的标准有两种:
- 使用 BEST_EFFORT_RELIABILITY_QOS 时,当接收到序列号更大的样本时,尚未接收的样本即被视为丢失。
- 使用 RELIABLE_RELIABILITY_QOS 时,当 DataWriter 通过 RTPS HEARTBEAT 子消息告知样本不再可用时,尚未接收的样本即被视为丢失。
状态数据成员列表:
| Data Member Name | Type |
|---|---|
total_count |
int32_t |
total_count_change |
int32_t |
- total_count:当前 DataReader 所在主题下丢失样本的累计总数。
- total_count_change:自上次调用 on_sample_lost() 或读取状态以来,total_count 的变化量。其值只能为正数或零。
3.1.3.8 SampleRejectedStatus
每当传入的数据样本被 DataReader 拒绝时,此状态都会发生变化。拒绝的原因由 SampleRejectedStatusKind 定义。更多信息请参见 SampleRejectedStatus。
状态数据成员列表:
| Data Member Name | Type |
|---|---|
total_count |
int32_t |
total_count_change |
int32_t |
last_reason |
SampleRejectedStatusKind |
last_instance_handle |
InstanceHandle_t |
- total_count:当前 DataReader 所在主题下被拒绝样本的累计总数。
- total_count_change:自上次调用 on_sample_rejected() 或读取状态以来,total_count 的变化量。其值只能为正数或零。
- last_reason:最后一个被拒绝样本的拒绝原因。如果从未拒绝过任何样本,其值为 NOT_REJECTED。更多详情请参见 SampleRejectedStatusKind。
- last_instance_handle:最后一个样本被拒绝的实例的句柄。如果从未拒绝过任何样本,其值为 c_InstanceHandle_Unknown。
3.1.3.8.1 SampleRejectedStatusKind
在 Fast DDS 中,样本可能由于资源限制原因被拒绝。然而,样本被拒绝并不意味着它们丢失了,即被拒绝的样本将来可能会被接受。
SampleRejectedStatusKind 指定了拒绝的原因:
- NOT_REJECTED:指定样本未被拒绝。
- REJECTED_BY_SAMPLES_LIMIT:指定样本因没有足够的资源存储而被拒绝。即使有空闲资源,但如果这些资源必须保证可用于其他样本,也可能发生这种情况。这种情况发生在 RTPS 层,当存在尚未接收到的序列号较低的样本,且没有足够的资源容纳所有这些样本(因为已达到 max_samples 限制)时出现。
- REJECTED_BY_INSTANCES_LIMIT:指定样本因没有足够的资源分配其实例而被拒绝。这种情况发生在 DDS 层,更确切地说是在 DataReader 的历史记录中,当样本对应于一个新实例,中间件应为其预留资源,但历史记录的实例数已达到 max_instances 限制时出现。
- REJECTED_BY_SAMPLES_PER_INSTANCE_LIMIT:指定样本因其实例内没有足够的资源存储而被拒绝。这种情况发生在 DDS 层,更确切地说是在 DataReader 的历史记录中,当 DataReader 配置为 KEEP_ALL_HISTORY_QOS 且实例的样本数已达到 max_samples_per_instance 限制时出现。
3.1.3.9 SubscriptionMatchedStatus
每当 DataReader 发现一个主题匹配、具有公共分区且 QoS 兼容的 DataWriter,或者与之前被认为匹配的 DataWriter 停止匹配时,此状态都会发生变化。参见 SubscriptionMatchedStatus。
状态数据成员列表:
| Data Member Name | Type |
|---|---|
total_count |
int32_t |
total_count_change |
int32_t |
current_count |
int32_t |
current_count_change |
int32_t |
last_publication_handle |
InstanceHandle_t |
- total_count:累计总数,即已发现的、在同一主题上发布且具有公共分区和兼容 QoS 的远程 DataWriter 数量。它们目前可能并未全部处于匹配状态。
- total_count_change:自上次调用 on_subscription_matched() 或读取状态以来,total_count 的变化量。其值只能为零或正数。
- current_count:当前与此 DataReader 匹配的远程 DataWriter 数量。
- current_count_change:自上次调用 on_subscription_matched() 或读取状态以来,current_count 的变化量。其值可以为正数或负数。
- last_publication_handle:最后与此 DataReader 匹配的 DataWriter 的句柄。如果从未发生过匹配,其值为 c_InstanceHandle_Unknown。
3.1.3.10 LivelinessLostStatus
每当 DataWriter 在其 DataWriterQos 配置的周期内未能断言其活性时,此状态都会发生变化。这意味着匹配的 DataReader 实体将认为该 DataWriter 不再存活。参见 LivelinessLostStatus。
状态数据成员列表:
| Data Member Name | Type |
|---|---|
total_count |
int32_t |
total_count_change |
int32_t |
- total_count:累计总数,即 DataWriter 在其 DataWriterQos 配置的周期内未能断言其活性,从而被视为非存活的次数。当 DataWriter 已被视为非存活,并仅仅在另一个活性周期内继续保持非存活状态时,此计数不会改变。
- total_count_change:自上次调用 on_liveliness_lost() 或读取状态以来,total_count 的变化量。其值只能为零或正数。
3.1.3.11 OfferedDeadlineMissedStatus
每当 DataWriter 在其 DataWriterQos 配置的截止期限内未能提供数据时,此状态都会发生变化。参见 OfferedDeadlineMissedStatus。
状态数据成员列表:
| Data Member Name | Type |
|---|---|
total_count |
int32_t |
total_count_change |
int32_t |
last_instance_handle |
InstanceHandle_t |
- total_count:累计总数,即当前 DataWriter 写入的任何实例错过截止时间的次数。由于截止期限独立应用于主题的每个实例,因此对于在截止期限内未发送数据的每个实例,计数将增加一。
- total_count_change:自上次调用 on_offered_deadline_missed() 或读取状态以来,total_count 的变化量。其值只能为零或正数。
- last_instance_handle:最后一个错过截止时间的实例的句柄。如果从未错过截止时间,其值为 c_InstanceHandle_Unknown。
3.1.3.12 OfferedIncompatibleQosStatus
每当 DataWriter 发现一个 DataReader,其主题匹配且具有公共分区,但 QoS 配置与 DataWriter 上定义的配置不兼容时,此状态都会发生变化。参见 OfferedIncompatibleQosStatus。
状态数据成员列表:
| Data Member Name | Type |
|---|---|
total_count |
int32_t |
total_count_change |
int32_t |
last_policy_id |
QosPolicyId_t |
policies |
QosPolicyCountSeq |
- total_count:累计总数,即发现匹配主题且具有公共分区,但 QoS 配置与 DataWriter 上定义的配置不兼容的 DataReader 数量。
- total_count_change:自上次调用 on_offered_incompatible_qos() 或读取状态以来,total_count 的变化量。其值只能为零或正数。
- last_policy_id:被发现与当前 DataWriter 不兼容的某个策略的策略 ID。如果多个策略碰巧不兼容,则此成员中只报告其中一个。
- policies:一个集合,为每个策略保存该策略被发现与匹配主题且具有公共分区的远程 DataReader 所请求的策略不兼容的总次数。有关每个策略存储的更多信息,请参见 QosPolicyCountSeq 和 QosPolicyCount。
3.1.3.13 PublicationMatchedStatus
每当 DataWriter 发现一个主题匹配、具有公共分区且 QoS 兼容的 DataReader,或者与之前被认为匹配的 DataReader 停止匹配时,此状态都会发生变化。参见 PublicationMatchedStatus。
状态数据成员列表:
| Data Member Name | Type |
|---|---|
total_count |
int32_t |
total_count_change |
int32_t |
current_count |
int32_t |
current_count_change |
int32_t |
last_subscription_handle |
InstanceHandle_t |
- total_count:累计总数,即已发现的、在同一主题上订阅且具有公共分区和兼容 QoS 的远程 DataReader 数量。它们目前可能并未全部处于匹配状态。
- total_count_change:自上次调用 on_publication_matched() 或读取状态以来,total_count 的变化量。其值只能为零或正数。
- current_count:当前与此 DataWriter 匹配的远程 DataReader 数量。
- current_count_change:自上次调用 on_publication_matched() 或读取状态以来,current_count 的变化量。其值可以为正数或负数。
- last_subscription_handle:最后与此 DataWriter 匹配的 DataReader 的句柄。如果从未发生过匹配,其值为 c_InstanceHandle_Unknown。
3.1.4 Conditions and Wait-sets(条件和等待集)
条件(与等待集结合使用)提供了一种替代机制,允许中间件将通信状态变化(包括数据到达)通知给应用程序。
此机制是基于等待的。其一般使用模式如下:
- 应用程序通过 Condition 对象(GuardCondition、StatusCondition 或 ReadCondition)指明它想要获取的相关信息,并通过 attach_condition() 调用将它们附加到一个等待集(Wait-set)上。
- 然后,它通过 wait() 调用在该等待集上等待,直到一个或多个 Condition 对象的触发值变为 true。
- 然后,它使用 wait() 的结果(即 trigger_value == true 的 Condition 对象列表),通过调用以下方法来实际获取信息:
- 当条件是一个 StatusCondition 且状态变化指的是普通通信状态时,首先调用 get_status_changes(),然后使用 StatusMask::is_active() 方法检查结果中是否有相关变化,最后在相关实体上调用 get_<communication_status>。有关可查询的不同状态的附加信息,请参阅《状态》部分。
- 当条件是一个 StatusCondition 且状态变化指的是 DataOnReaders 时,调用 get_status_changes(),然后在相关的订阅者上调用 Subscriber::get_datareaders()。
- 当条件是一个 StatusCondition 且状态变化指的是 DataAvailable 时,调用 get_status_changes(),然后在相关的 DataReader 上调用 DataReader::read() 或 DataReader::take()。
- 当条件是一个 ReadCondition 时,直接在 DataReader 上调用 DataReader::read_w_condition() 或 DataReader::take_w_condition(),并将该条件作为参数传入。
- 当某个条件不再相关时,可以通过 detach_condition() 调用将其从等待集中分离。
第一步通常在初始化阶段完成,而其他步骤则放在应用程序的主循环中。
class ApplicationJob
{
WaitSet wait_set_;
GuardCondition terminate_condition_;
std::thread thread_;
void main_loop()
{
// Main loop is repeated until the terminate condition is triggered
while (false == terminate_condition_.get_trigger_value())
{
// Wait for any of the conditions to be triggered
ReturnCode_t ret_code;
ConditionSeq triggered_conditions;
ret_code = wait_set_.wait(triggered_conditions, eprosima::fastdds::dds::c_TimeInfinite);
if (RETCODE_OK != ret_code)
{
// ... handle error
continue;
}
// Process triggered conditions
for (Condition* cond : triggered_conditions)
{
StatusCondition* status_cond = dynamic_cast<StatusCondition*>(cond);
if (nullptr != status_cond)
{
Entity* entity = status_cond->get_entity();
StatusMask changed_statuses = entity->get_status_changes();
// Process status. Liveliness changed and data available are depicted as an example
if (changed_statuses.is_active(StatusMask::liveliness_changed()))
{
std::cout << "Liveliness changed reported for entity " <<
entity->get_instance_handle() <<
std::endl;
}
if (changed_statuses.is_active(StatusMask::data_available()))
{
std::cout << "Data avilable on reader " << entity->get_instance_handle() << std::endl;
FooSeq data_seq;
SampleInfoSeq info_seq;
DataReader* reader = static_cast<DataReader*>(entity);
// Process all the samples until no one is returned
while (RETCODE_OK == reader->take(data_seq, info_seq,
LENGTH_UNLIMITED, ANY_SAMPLE_STATE,
ANY_VIEW_STATE, ANY_INSTANCE_STATE))
{
// Both info_seq.length() and data_seq.length() will have the number of samples returned
for (FooSeq::size_type n = 0; n < info_seq.length(); ++n)
{
// Only samples with valid data should be accessed
if (info_seq[n].valid_data &&
reader->is_sample_valid(&data_seq[n], &info_seq[n]))
{
// Process sample on data_seq[n]
}
}
// must return the loaned sequences when done processing
reader->return_loan(data_seq, info_seq);
}
}
}
}
}
}
public:
ApplicationJob(
const std::vector<DataReader*>& readers,
const std::vector<DataWriter*>& writers)
{
// Add a GuardCondition, so we can signal the processing thread to stop
wait_set_.attach_condition(terminate_condition_);
// Add the status condition of every reader and writer
for (DataReader* reader : readers)
{
wait_set_.attach_condition(reader->get_statuscondition());
}
for (DataWriter* writer : writers)
{
wait_set_.attach_condition(writer->get_statuscondition());
}
thread_ = std::thread(&ApplicationJob::main_loop, this);
}
~ApplicationJob()
{
// Signal the GuardCondition to force the WaitSet to wake up
terminate_condition_.set_trigger_value(true);
// Wait for the thread to finish
thread_.join();
}
};
// Application initialization
ReturnCode_t ret_code;
std::vector<DataReader*> application_readers;
std::vector<DataWriter*> application_writers;
// Create the participant, topics, readers, and writers.
ret_code = create_dds_application(application_readers, application_writers);
if (RETCODE_OK != ret_code)
{
// ... handle error
return;
}
{
ApplicationJob main_loop_thread(application_readers, application_writers);
// ... wait for application termination signaling (signal handler, user input, etc)
// ... Destructor of ApplicationJob takes care of stopping the processing thread
}
// Destroy readers, writers, topics, and participant
destroy_dds_application();
如果在等待集上调用 wait() 操作时,其所有附加条件的触发值都为 false,则该操作将阻塞调用线程。一旦任何附加条件的触发值变为 true,线程将被唤醒,并且 wait() 操作将返回 RETCODE_OK。
3.1.4.1 GuardCondition
一种条件,其触发值完全由应用程序通过其 set_trigger_value() 操作控制。
3.1.4.2 StatusCondition
一种条件,每当实体的通信状态发生变化时就会触发。
StatusCondition 对特定通信状态的敏感性,通过 set_enabled_statuses() 操作在条件上设置的 enabled_statuses 列表来控制。
3.1.4.3 ReadCondition
一种条件,当创建它的 DataReader 包含至少一个样本,且该样本的样本状态(SampleState)、视图状态(ViewState)和实例状态(InstanceState)与 ReadCondition 中指定的状态相匹配时,该条件就会触发。
ReadCondition 的触发值依赖于关联 DataReader 上是否存在样本,这一事实意味着,单次 take 操作可能会潜在地改变多个 ReadCondition 条件的触发值。例如,如果所有样本都被取走,那么与该 DataReader 关联的任何之前被触发的 ReadCondition 都会发现其触发值变为 false。请注意,这并不保证单独附加到这些条件上的 WaitSet 对象不会被唤醒。一旦某个条件的 trigger_value == true,它就可能唤醒附加的等待集。条件转换为 trigger_value == false 并不一定"取消唤醒"等待集,因为"取消唤醒"通常是不可能的。其结果是,一个在 WaitSet 上被阻塞的应用程序可能从 wait 调用返回时得到一个条件列表,其中一些条件可能不再处于触发状态。这也可能是用户操作的结果。用户手动调用 set_trigger_value() 也可能触发相同的行为。如果有多个线程并发地等待在不同的 WaitSet 对象上,并取走与同一个 DataReader 实体相关联的数据,这种情况是不可避免的。
为了进一步说明,考虑以下示例:一个 ReadCondition,其 sample_state_mask = {NOT_READ},每当有新样本到达时,其 trigger_value 将为 true,并且一旦所有新到达的样本都被读取(因此其状态变为 READ)或取走(因此它们不再由 DataReader 管理),其 trigger_value 就会变为 false。然而,如果同一个 ReadCondition 的 sample_state_mask = {READ, NOT_READ},那么只有当所有新到达的样本都被取走时,trigger_value 才会变为 false(仅仅读取它们是不够的,因为那只会将 SampleState 更改为 READ,而 READ 仍然与 ReadCondition 上的掩码重叠)。