dust_dds/dds/subscription/
data_reader.rs

1use super::subscriber::Subscriber;
2use crate::{
3    builtin_topics::PublicationBuiltinTopicData,
4    condition::StatusCondition,
5    dds_async::data_reader::DataReaderAsync,
6    infrastructure::{
7        error::DdsResult,
8        instance::InstanceHandle,
9        qos::{DataReaderQos, QosKind},
10        sample_info::{InstanceStateKind, Sample, SampleStateKind, ViewStateKind},
11        status::{
12            LivelinessChangedStatus, RequestedDeadlineMissedStatus, RequestedIncompatibleQosStatus,
13            SampleLostStatus, SampleRejectedStatus, StatusKind, SubscriptionMatchedStatus,
14        },
15        time::Duration,
16    },
17    runtime::DdsRuntime,
18    subscription::data_reader_listener::DataReaderListener,
19    topic_definition::topic_description::TopicDescription,
20};
21use alloc::vec::Vec;
22
23/// A [`DataReader`] allows the application (1) to declare the data it wishes to receive (i.e., make a subscription) and (2) to access the
24/// data received by the attached [`Subscriber`].
25///
26/// A DataReader refers to exactly one [`Topic`] that identifies the data to be read. The subscription has a unique resulting type.
27/// The data-reader may give access to several instances of the resulting type, which can be distinguished from each other by their key.
28pub struct DataReader<R: DdsRuntime, Foo> {
29    reader_async: DataReaderAsync<R, Foo>,
30}
31
32impl<R: DdsRuntime, Foo> DataReader<R, Foo> {
33    pub(crate) fn reader_async(&self) -> &DataReaderAsync<R, Foo> {
34        &self.reader_async
35    }
36}
37
38impl<R: DdsRuntime, Foo> From<DataReaderAsync<R, Foo>> for DataReader<R, Foo> {
39    fn from(value: DataReaderAsync<R, Foo>) -> Self {
40        Self {
41            reader_async: value,
42        }
43    }
44}
45
46impl<R: DdsRuntime, Foo> Clone for DataReader<R, Foo> {
47    fn clone(&self) -> Self {
48        Self {
49            reader_async: self.reader_async.clone(),
50        }
51    }
52}
53
54impl<R: DdsRuntime, Foo> DataReader<R, Foo> {
55    /// This operation accesses a collection of [`Sample`] from the [`DataReader`]. The size of the returned collection will
56    /// be limited to the specified `max_samples`. The properties of the data values collection and the setting of the
57    /// [`PresentationQosPolicy`](crate::infrastructure::qos_policy::PresentationQosPolicy) may impose further limits
58    /// on the size of the returned list:
59    /// 1. If [`PresentationQosPolicy::access_scope`](crate::infrastructure::qos_policy::PresentationQosPolicy) is
60    /// [`PresentationQosPolicyAccessScopeKind::Instance`](crate::infrastructure::qos_policy::PresentationQosPolicyAccessScopeKind),
61    /// then the returned collection is a list where samples belonging to the same data-instance are consecutive.
62    /// 2. If [`PresentationQosPolicy::access_scope`](crate::infrastructure::qos_policy::PresentationQosPolicy) is
63    /// [`PresentationQosPolicyAccessScopeKind::Topic`](crate::infrastructure::qos_policy::PresentationQosPolicyAccessScopeKind) and
64    /// [`PresentationQosPolicy::ordered_access`](crate::infrastructure::qos_policy::PresentationQosPolicy) is set to [`false`],
65    /// then the returned collection is a list where samples belonging to the same data-instance are consecutive.
66    /// 3. If [`PresentationQosPolicy::access_scope`](crate::infrastructure::qos_policy::PresentationQosPolicy) is
67    /// [`PresentationQosPolicyAccessScopeKind::Topic`](crate::infrastructure::qos_policy::PresentationQosPolicyAccessScopeKind) and
68    /// [`PresentationQosPolicy::ordered_access`](crate::infrastructure::qos_policy::PresentationQosPolicy) is set to [`true`],
69    /// then the returned collection is a list where samples belonging to the same instance may or may not be consecutive.
70    /// This is because to preserve order it may be necessary to mix samples from different instances.
71    ///
72    /// In any case, the relative order between the samples of one instance is consistent with the
73    /// [`DestinationOrderQosPolicy`](crate::infrastructure::qos_policy::DestinationOrderQosPolicy):
74    /// - If [`DestinationOrderQosPolicyKind::ByReceptionTimestamp`](crate::infrastructure::qos_policy::DestinationOrderQosPolicyKind),
75    /// samples belonging to the same instances will appear in the relative order in which there were received
76    /// (FIFO, earlier samples ahead of the later samples).
77    /// - If  [`DestinationOrderQosPolicyKind::BySourceTimestamp`](crate::infrastructure::qos_policy::DestinationOrderQosPolicyKind),
78    /// samples belonging to the same instances will appear in the relative order implied by the `source_timestamp`
79    /// (FIFO, smaller values of `source_timestamp` ahead of the larger values).
80    ///
81    /// Each [`Sample`] contains the data and a [`SampleInfo`] which provides information, such as the
82    /// [`SampleInfo::source_timestamp`], the [`SampleInfo::sample_state`], [`SampleInfo::view_state`], and
83    /// [`SampleInfo::instance_state`], etc., about the corresponding sample.
84    /// Some elements in the returned collection may not have valid data. If the [`SampleInfo::instance_state`] is
85    /// [`InstanceStateKind::NotAliveDisposed`] or [`InstanceStateKind::NotAliveNoWriters`], then the last sample
86    /// for that instance in the collection, that is, the one whose `[`SampleInfo::sample_rank`]==0` does not contain
87    /// valid data. Samples that contain no data do not count towards the limits imposed by the
88    /// [`ResourceLimitsQosPolicy`](crate::infrastructure::qos_policy::ResourceLimitsQosPolicy).
89    /// The act of reading a sample sets its [`SampleInfo::sample_state`] to [`SampleStateKind::Read`]. If the sample
90    /// belongs to the most recent generation of the instance, it will also set the [`SampleInfo::view_state`]
91    /// of the instance to [`ViewStateKind::NotNew`]. It will not affect the  [`SampleInfo::instance_state`] of the instance.
92    ///
93    /// If the DataReader has no samples that meet the constraints, the return value will be
94    /// [`DdsError::NoData`](crate::infrastructure::error::DdsError).
95    #[tracing::instrument(skip(self))]
96    pub fn read(
97        &self,
98        max_samples: i32,
99        sample_states: &[SampleStateKind],
100        view_states: &[ViewStateKind],
101        instance_states: &[InstanceStateKind],
102    ) -> DdsResult<Vec<Sample<Foo>>> {
103        R::block_on(self.reader_async.read(
104            max_samples,
105            sample_states,
106            view_states,
107            instance_states,
108        ))
109    }
110
111    /// This operation accesses a collection of [`Sample`] from the [`DataReader`]. This operation uses the same
112    /// logic as the [`DataReader::read`]. The only difference with read is that the
113    /// sampled returned by [`DataReader::take`] will no longer be accessible to successive calls to read or take.
114    #[tracing::instrument(skip(self))]
115    pub fn take(
116        &self,
117        max_samples: i32,
118        sample_states: &[SampleStateKind],
119        view_states: &[ViewStateKind],
120        instance_states: &[InstanceStateKind],
121    ) -> DdsResult<Vec<Sample<Foo>>> {
122        R::block_on(self.reader_async.take(
123            max_samples,
124            sample_states,
125            view_states,
126            instance_states,
127        ))
128    }
129
130    /// This operation reads the next, non-previously accessed [`Sample`] value from the [`DataReader`].
131    /// The implied order among the samples stored in the [`DataReader`] is the same as for the [`DataReader::read`]
132    /// operation. This operation is semantically equivalent to the read operation where the input Data sequence has
133    /// `max_samples=1`, the `sample_states = &[SampleStateKind::NotRead]`, `view_states=ANY_VIEW_STATE`, and
134    /// `instance_states=ANY_INSTANCE_STATE`.
135    /// This operation provides a simplified API to 'read' samples avoiding the need for the application to manage
136    /// sequences and specify states.
137    #[tracing::instrument(skip(self))]
138    pub fn read_next_sample(&self) -> DdsResult<Sample<Foo>> {
139        R::block_on(self.reader_async.read_next_sample())
140    }
141
142    /// This operation takes the next, non-previously accessed [`Sample`] value from the [`DataReader`].
143    /// The implied order among the samples stored in the [`DataReader`] is the same as for the [`DataReader::read`]
144    /// operation. This operation is semantically equivalent to the read operation where the input Data sequence has
145    /// `max_samples=1`, the `sample_states = &[SampleStateKind::NotRead]`, `view_states=ANY_VIEW_STATE`, and
146    /// `instance_states=ANY_INSTANCE_STATE`.
147    /// This operation provides a simplified API to 'take' samples avoiding the need for the application to manage
148    /// sequences and specify states.
149    #[tracing::instrument(skip(self))]
150    pub fn take_next_sample(&self) -> DdsResult<Sample<Foo>> {
151        R::block_on(self.reader_async.take_next_sample())
152    }
153
154    /// This operation accesses a collection of [`Sample`] from the [`DataReader`]. The
155    /// behavior is identical to [`DataReader::read`] except that all samples returned
156    /// belong to the single specified instance whose handle is `a_handle`.
157    /// Upon successful return, the collection will contain samples all belonging to the
158    /// same instance. The corresponding [`SampleInfo`] verifies [`SampleInfo::instance_handle`] == a_handle.
159    /// This operation return [`DdsError::BadParameter`](crate::infrastructure::error::DdsError)
160    /// if the [`InstanceHandle`] `a_handle` does not correspond to an existing
161    /// data object known to the [`DataReader`].
162    #[tracing::instrument(skip(self))]
163    pub fn read_instance(
164        &self,
165        max_samples: i32,
166        a_handle: InstanceHandle,
167        sample_states: &[SampleStateKind],
168        view_states: &[ViewStateKind],
169        instance_states: &[InstanceStateKind],
170    ) -> DdsResult<Vec<Sample<Foo>>> {
171        R::block_on(self.reader_async.read_instance(
172            max_samples,
173            a_handle,
174            sample_states,
175            view_states,
176            instance_states,
177        ))
178    }
179
180    /// This operation accesses a collection of [`Sample`] from the [`DataReader`]. The
181    /// behavior is identical to [`DataReader::take`] except that all samples returned
182    /// belong to the single specified instance whose handle is `a_handle`.
183    /// Upon successful return, the collection will contain samples all belonging to the
184    /// same instance. The corresponding [`SampleInfo`] verifies [`SampleInfo::instance_handle`] == a_handle.
185    /// This operation return [`DdsError::BadParameter`](crate::infrastructure::error::DdsError)
186    /// if the [`InstanceHandle`] `a_handle` does not correspond to an existing
187    /// data object known to the [`DataReader`].
188    #[tracing::instrument(skip(self))]
189    pub fn take_instance(
190        &self,
191        max_samples: i32,
192        a_handle: InstanceHandle,
193        sample_states: &[SampleStateKind],
194        view_states: &[ViewStateKind],
195        instance_states: &[InstanceStateKind],
196    ) -> DdsResult<Vec<Sample<Foo>>> {
197        R::block_on(self.reader_async.take_instance(
198            max_samples,
199            a_handle,
200            sample_states,
201            view_states,
202            instance_states,
203        ))
204    }
205
206    /// This operation accesses a collection of [`Sample`] from the [`DataReader`] where all the samples belong to a single instance.
207    /// The behavior is similar to [`DataReader::read_instance`] except that the actual instance is not directly specified.
208    /// Rather the samples will all belong to the 'next' instance with instance_handle 'greater' than the specified
209    /// `previous_handle` that has available samples.
210    /// This operation implies the existence of a total order *greater-than* relationship between the instance handles.
211    /// The specifics of this relationship are not all important and are implementation specific. The important thing is that,
212    /// according to the middleware, all instances are ordered relative to each other. This ordering is between the instance handles
213    /// and it does not depend on the state of the instance (e.g., whether it has data or not) and must be defined even for
214    /// instance handles that do not correspond to instances currently managed by the [`DataReader`].
215    /// The behavior of this operation is as if [`DataReader::read_instance`] was invoked passing the smallest `instance_handle`
216    /// among all the ones that (a) are greater than `previous_handle` and (b) have available samples (i.e., samples that meet the
217    /// constraints imposed by the specified states). If [`None`] is used as the `previous_handle` argument the operation will
218    /// return the samples for the instance which has the smallest instance_handle among allthe instances that contain available samples.
219    /// The operation [`DataReader::read_next_instance`] is intended to be used in an application-driven iteration where the application starts by
220    /// passing `previous_handle==None`, examines the samples returned, and then uses the [`SampleInfo::instance_handle`] returned in
221    /// as the value of the `previous_handle` argument to the next call to [`DataReader::read_next_instance`]. The iteration continues
222    /// until the operation returns the value [`DdsError::NoData`](crate::infrastructure::error::DdsError).
223    /// Note that it is possible to call this operation with a `previous_handle` that does not correspond to an
224    /// instance currently managed by the [`DataReader`]. One practical situation where this may occur is when an application is iterating
225    /// though all the instances, takes all the samples of a [`InstanceStateKind::NotAliveNoWriters`] instance (at which point the
226    /// instance information may be removed, and thus the handle becomes invalid) and tries to read the next instance.
227    /// The behavior of this operation generally follows the same rules as the [`DataReader::read`] operation regarding the pre-conditions
228    /// and post-conditions and returned values.
229    #[tracing::instrument(skip(self))]
230    pub fn read_next_instance(
231        &self,
232        max_samples: i32,
233        previous_handle: Option<InstanceHandle>,
234        sample_states: &[SampleStateKind],
235        view_states: &[ViewStateKind],
236        instance_states: &[InstanceStateKind],
237    ) -> DdsResult<Vec<Sample<Foo>>> {
238        R::block_on(self.reader_async.read_next_instance(
239            max_samples,
240            previous_handle,
241            sample_states,
242            view_states,
243            instance_states,
244        ))
245    }
246
247    /// This operation accesses a collection of [`Sample`] values from the [`DataReader`] and removes them from the [`DataReader`].
248    /// This operation has the same behavior as [`DataReader::read_next_instance`] except that the samples are 'taken' from the [`DataReader`] such
249    /// that they are no longer accessible via subsequent 'read' or 'take' operations.
250    #[tracing::instrument(skip(self))]
251    pub fn take_next_instance(
252        &self,
253        max_samples: i32,
254        previous_handle: Option<InstanceHandle>,
255        sample_states: &[SampleStateKind],
256        view_states: &[ViewStateKind],
257        instance_states: &[InstanceStateKind],
258    ) -> DdsResult<Vec<Sample<Foo>>> {
259        R::block_on(self.reader_async.take_next_instance(
260            max_samples,
261            previous_handle,
262            sample_states,
263            view_states,
264            instance_states,
265        ))
266    }
267
268    /// This operation can be used to retrieve the instance key that corresponds to an `handle`.
269    /// The operation will only fill the fields that form the key inside the `key_holder` instance.
270    /// This operation may return [`DdsError::BadParameter`](crate::infrastructure::error::DdsError)
271    /// if the [`InstanceHandle`] `handle` does not correspond to an existing data object known to the [`DataReader`].
272    #[tracing::instrument(skip(self, key_holder))]
273    pub fn get_key_value(&self, key_holder: &mut Foo, handle: InstanceHandle) -> DdsResult<()> {
274        R::block_on(self.reader_async.get_key_value(key_holder, handle))
275    }
276
277    /// This operation takes as a parameter an instance and returns an [`InstanceHandle`] handle
278    /// that can be used in subsequent operations that accept an instance handle as an argument.
279    /// The instance parameter is only used for the purpose of examining the fields that define the
280    /// key. This operation does not register the instance in question. If the instance has not
281    /// been previously registered, or if for any other reason the Service is unable to provide
282    /// an instance handle, the operation will succeed and return [`None`].
283    #[tracing::instrument(skip(self, instance))]
284    pub fn lookup_instance(&self, instance: &Foo) -> DdsResult<Option<InstanceHandle>> {
285        R::block_on(self.reader_async.lookup_instance(instance))
286    }
287}
288
289impl<R: DdsRuntime, Foo> DataReader<R, Foo> {
290    /// This operation allows access to the [`LivelinessChangedStatus`].
291    #[tracing::instrument(skip(self))]
292    pub fn get_liveliness_changed_status(&self) -> DdsResult<LivelinessChangedStatus> {
293        R::block_on(self.reader_async.get_liveliness_changed_status())
294    }
295
296    /// This operation allows access to the [`RequestedDeadlineMissedStatus`].
297    #[tracing::instrument(skip(self))]
298    pub fn get_requested_deadline_missed_status(&self) -> DdsResult<RequestedDeadlineMissedStatus> {
299        R::block_on(self.reader_async.get_requested_deadline_missed_status())
300    }
301
302    /// This operation allows access to the [`RequestedIncompatibleQosStatus`].
303    #[tracing::instrument(skip(self))]
304    pub fn get_requested_incompatible_qos_status(
305        &self,
306    ) -> DdsResult<RequestedIncompatibleQosStatus> {
307        R::block_on(self.reader_async.get_requested_incompatible_qos_status())
308    }
309
310    /// This operation allows access to the [`SampleLostStatus`].
311    #[tracing::instrument(skip(self))]
312    pub fn get_sample_lost_status(&self) -> DdsResult<SampleLostStatus> {
313        R::block_on(self.reader_async.get_sample_lost_status())
314    }
315
316    /// This operation allows access to the [`SampleRejectedStatus`].
317    #[tracing::instrument(skip(self))]
318    pub fn get_sample_rejected_status(&self) -> DdsResult<SampleRejectedStatus> {
319        R::block_on(self.reader_async.get_sample_rejected_status())
320    }
321
322    /// This operation allows access to the [`SubscriptionMatchedStatus`].
323    #[tracing::instrument(skip(self))]
324    pub fn get_subscription_matched_status(&self) -> DdsResult<SubscriptionMatchedStatus> {
325        R::block_on(self.reader_async.get_subscription_matched_status())
326    }
327
328    /// This operation returns the [`Topic`] associated with the [`DataReader`]. This is the same [`Topic`]
329    /// that was used to create the [`DataReader`].
330    #[tracing::instrument(skip(self))]
331    pub fn get_topicdescription(&self) -> TopicDescription<R> {
332        self.reader_async.get_topicdescription().into()
333    }
334
335    /// This operation returns the [`Subscriber`] to which the [`DataReader`] belongs.
336    #[tracing::instrument(skip(self))]
337    pub fn get_subscriber(&self) -> Subscriber<R> {
338        Subscriber::from(self.reader_async.get_subscriber())
339    }
340
341    /// This operation blocks the calling thread until either all *historical* data is received, or else the
342    /// duration specified by the `max_wait` parameter elapses, whichever happens first.
343    /// A return value of [`Ok`] indicates that all the *historical* data was received;
344    /// a return value of [`DdsError`](crate::infrastructure::error::DdsError) indicates that `max_wait`
345    /// elapsed before all the data was received.
346    /// This operation is intended only for [`DataReader`] entities that have a non-VOLATILE
347    /// [`DurabilityQosPolicy`](crate::infrastructure::qos_policy::DurabilityQosPolicy).
348    /// As soon as an application enables a non-VOLATILE [`DataReader`] it will start receiving both
349    /// *historical* data, i.e., the data that was written prior to the time the [`DataReader`] joined the
350    /// domain, as well as any new data written by the [`DataWriter`](crate::publication::data_writer::DataWriter) entities.
351    /// There are situations where the application logic may require the application to wait until all *historical*
352    /// data is received.
353    #[tracing::instrument(skip(self))]
354    pub fn wait_for_historical_data(&self, max_wait: Duration) -> DdsResult<()> {
355        R::block_on(self.reader_async.wait_for_historical_data(max_wait))
356    }
357
358    /// This operation retrieves information on a publication that is currently *associated* with the [`DataReader`];
359    /// that is, a publication with a matching [`Topic`] and compatible qos that the application  has not indicated should be ignored by means of the
360    /// [`DomainParticipant::ignore_publication`](crate::domain::domain_participant::DomainParticipant) operation.
361    /// The `publication_handle` must correspond to a publication currently associated with the [`DataReader`] otherwise the operation
362    /// will fail and return [`DdsError::BadParameter`](crate::infrastructure::error::DdsError).
363    /// The operation [`DataReader::get_matched_publications`] can be used to find the publications that are
364    /// currently matched with the [`DataReader`].
365    #[tracing::instrument(skip(self))]
366    pub fn get_matched_publication_data(
367        &self,
368        publication_handle: InstanceHandle,
369    ) -> DdsResult<PublicationBuiltinTopicData> {
370        R::block_on(
371            self.reader_async
372                .get_matched_publication_data(publication_handle),
373        )
374    }
375
376    /// This operation retrieves the list of publications currently *associated* with the [`DataReader`]; that is, publications that have a
377    /// matching [`Topic`] and compatible qos that the application has not indicated should be ignored by means of the
378    /// [`DomainParticipant::ignore_publication`](crate::domain::domain_participant::DomainParticipant) operation.
379    /// The handles returned are the ones that are used by the DDS implementation to locally identify
380    /// the corresponding matched [`DataWriter`](crate::publication::data_writer::DataWriter) entities. These handles match the ones that appear in the
381    /// [`SampleInfo::instance_handle`](crate::subscription::sample_info::SampleInfo) when reading the *DCPSPublications* builtin topic.
382    #[tracing::instrument(skip(self))]
383    pub fn get_matched_publications(&self) -> DdsResult<Vec<InstanceHandle>> {
384        R::block_on(self.reader_async.get_matched_publications())
385    }
386}
387
388impl<R: DdsRuntime, Foo> DataReader<R, Foo> {
389    /// This operation is used to set the QoS policies of the Entity and replacing the values of any policies previously set.
390    /// Certain policies are *immutable;* they can only be set at Entity creation time, or before the entity is made enabled.
391    /// If [`Self::set_qos()`] is invoked after the Entity is enabled and it attempts to change the value of an *immutable* policy, the operation will
392    /// fail and returns [`DdsError::ImmutablePolicy`](crate::infrastructure::error::DdsError).
393    /// Certain values of QoS policies can be incompatible with the settings of the other policies. This operation will also fail if it specifies
394    /// a set of values that once combined with the existing values would result in an inconsistent set of policies. In this case,
395    /// the return value is [`DdsError::InconsistentPolicy`](crate::infrastructure::error::DdsError).
396    /// The existing set of policies are only changed if the [`Self::set_qos()`] operation succeeds. This is indicated by the [`Ok`] return value. In all
397    /// other cases, none of the policies is modified.
398    /// The parameter `qos` can be set to [`QosKind::Default`] to indicate that the QoS of the Entity should be changed to match the current default QoS set in the Entity's factory.
399    /// The operation [`Self::set_qos()`] cannot modify the immutable QoS so a successful return of the operation indicates that the mutable QoS for the Entity has been
400    /// modified to match the current default for the Entity's factory.
401    #[tracing::instrument(skip(self))]
402    pub fn set_qos(&self, qos: QosKind<DataReaderQos>) -> DdsResult<()> {
403        R::block_on(self.reader_async.set_qos(qos))
404    }
405
406    /// This operation allows access to the existing set of [`DataReaderQos`] policies.
407    #[tracing::instrument(skip(self))]
408    pub fn get_qos(&self) -> DdsResult<DataReaderQos> {
409        R::block_on(self.reader_async.get_qos())
410    }
411
412    /// This operation allows access to the [`StatusCondition`] associated with the Entity. The returned
413    /// condition can then be added to a [`WaitSet`](crate::infrastructure::wait_set::WaitSet) so that the application can wait for specific status changes
414    /// that affect the Entity.
415    #[tracing::instrument(skip(self))]
416    pub fn get_statuscondition(&self) -> StatusCondition<R> {
417        StatusCondition::new(self.reader_async.get_statuscondition())
418    }
419
420    /// This operation retrieves the list of communication statuses in the Entity that are 'triggered.' That is, the list of statuses whose
421    /// value has changed since the last time the application read the status.
422    /// When the entity is first created or if the entity is not enabled, all communication statuses are in the *untriggered* state so the
423    /// list returned by the [`Self::get_status_changes`] operation will be empty.
424    /// The list of statuses returned by the [`Self::get_status_changes`] operation refers to the status that are triggered on the Entity itself
425    /// and does not include statuses that apply to contained entities.
426    #[tracing::instrument(skip(self))]
427    pub fn get_status_changes(&self) -> DdsResult<Vec<StatusKind>> {
428        R::block_on(self.reader_async.get_status_changes())
429    }
430
431    /// This operation enables the Entity. Entity objects can be created either enabled or disabled. This is controlled by the value of
432    /// the [`EntityFactoryQosPolicy`](crate::infrastructure::qos_policy::EntityFactoryQosPolicy) on the corresponding factory for the Entity.
433    /// The default setting of [`EntityFactoryQosPolicy`](crate::infrastructure::qos_policy::EntityFactoryQosPolicy) is such that, by default, it is not necessary to explicitly call enable on newly
434    /// created entities.
435    /// The [`Self::enable()`] operation is idempotent. Calling [`Self::enable()`] on an already enabled Entity returns [`Ok`] and has no effect.
436    /// If an Entity has not yet been enabled, the following kinds of operations may be invoked on it:
437    /// - Operations to set or get an Entity's QoS policies (including default QoS policies) and listener
438    /// - [`Self::get_statuscondition()`]
439    /// - Factory and lookup operations
440    /// - [`Self::get_status_changes()`] and other get status operations (although the status of a disabled entity never changes)
441    /// Other operations may explicitly state that they may be called on disabled entities; those that do not will return the error
442    /// NotEnabled.
443    /// It is legal to delete an Entity that has not been enabled by calling the proper operation on its factory.
444    /// Entities created from a factory that is disabled, are created disabled regardless of the setting of the ENTITY_FACTORY Qos
445    /// policy.
446    /// Calling enable on an Entity whose factory is not enabled will fail and return PRECONDITION_NOT_MET.
447    /// If the `autoenable_created_entities` field of [`EntityFactoryQosPolicy`](crate::infrastructure::qos_policy::EntityFactoryQosPolicy) is set to [`true`], the [`Self::enable()`] operation on the factory will
448    /// automatically enable all entities created from the factory.
449    /// The Listeners associated with an entity are not called until the entity is enabled. Conditions associated with an entity that is not
450    /// enabled are *inactive,* that is, the operation [`StatusCondition::get_trigger_value()`] will always return `false`.
451    #[tracing::instrument(skip(self))]
452    pub fn enable(&self) -> DdsResult<()> {
453        R::block_on(self.reader_async.enable())
454    }
455
456    /// This operation returns the [`InstanceHandle`] that represents the Entity.
457    #[tracing::instrument(skip(self))]
458    pub fn get_instance_handle(&self) -> InstanceHandle {
459        R::block_on(self.reader_async.get_instance_handle())
460    }
461}
462
463impl<R: DdsRuntime, Foo> DataReader<R, Foo> {
464    /// This operation installs a Listener on the Entity. The listener will only be invoked on the changes of communication status
465    /// indicated by the specified mask. It is permitted to use [`None`] as the value of the listener. The [`None`] listener behaves
466    /// as a Listener whose operations perform no action.
467    /// Only one listener can be attached to each Entity. If a listener was already set, the operation [`Self::set_listener()`] will replace it with the
468    /// new one. Consequently if the value [`None`] is passed for the listener parameter to the [`Self::set_listener()`] operation, any existing listener
469    /// will be removed.
470    #[tracing::instrument(skip(self, a_listener))]
471    pub fn set_listener(
472        &self,
473        a_listener: Option<impl DataReaderListener<R, Foo> + Send + 'static>,
474        mask: &[StatusKind],
475    ) -> DdsResult<()> {
476        R::block_on(self.reader_async.set_listener(a_listener, mask))
477    }
478}