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}