1use std::{
2 collections::{BTreeMap, BTreeSet},
3 error::Error,
4 fmt,
5 pin::Pin,
6 sync::{
7 atomic::{AtomicBool, Ordering},
8 Arc, Mutex,
9 },
10};
11
12use futures::{
13 pin_mut, stream, stream::FusedStream, task, task::Poll, Future, FutureExt, Stream, StreamExt,
14};
15use async_channel::Receiver;
16#[allow(unused_imports)]
17use log::{debug, error, info, trace, warn};
18use serde::Serialize;
19use rustdds::{
20 dds::{CreateError, CreateResult},
21 *,
22};
23
24use crate::{
25 action::*,
26 builtin_interfaces,
27 context::{Context, DEFAULT_SUBSCRIPTION_QOS},
28 entities_info::{NodeEntitiesInfo, ParticipantEntitiesInfo},
29 gid::Gid,
30 log::Log,
31 names::*,
32 parameters::*,
33 pubsub::{Publisher, Subscription},
34 rcl_interfaces,
35 ros_time::ROSTime,
36 rosout::{NodeLoggingHandle, RosoutRaw},
37 service::{Client, Server, Service, ServiceMapping},
38};
39
40type ParameterFunc = dyn Fn(&str, &ParameterValue) -> SetParametersResult + Send + Sync;
41#[must_use]
48pub struct NodeOptions {
49 #[allow(dead_code)]
50 cli_args: Vec<String>,
51 #[allow(dead_code)]
52 use_global_arguments: bool, enable_rosout: bool, enable_rosout_reading: bool,
55 start_parameter_services: bool,
56 declared_parameters: Vec<Parameter>,
57 allow_undeclared_parameters: bool,
58 parameter_validator: Option<Box<ParameterFunc>>,
59 parameter_set_action: Option<Box<ParameterFunc>>,
60}
61
62impl NodeOptions {
63 pub fn new() -> NodeOptions {
65 NodeOptions {
68 cli_args: Vec::new(),
69 use_global_arguments: true,
70 enable_rosout: true,
71 enable_rosout_reading: false,
72 start_parameter_services: true,
73 declared_parameters: Vec::new(),
74 allow_undeclared_parameters: false,
75 parameter_validator: None,
76 parameter_set_action: None,
77 }
78 }
79 pub fn enable_rosout(self, enable_rosout: bool) -> NodeOptions {
80 NodeOptions {
81 enable_rosout,
82 ..self
83 }
84 }
85
86 pub fn read_rosout(self, enable_rosout_reading: bool) -> NodeOptions {
87 NodeOptions {
88 enable_rosout_reading,
89 ..self
90 }
91 }
92
93 pub fn declare_parameter(mut self, name: &str, value: ParameterValue) -> NodeOptions {
94 self.declared_parameters.push(Parameter {
95 name: name.to_owned(),
96 value,
97 });
98 self
100 }
101
102 pub fn parameter_validator(mut self, validator: Box<ParameterFunc>) -> NodeOptions {
103 self.parameter_validator = Some(validator);
104 self
105 }
106
107 pub fn parameter_set_action(mut self, action: Box<ParameterFunc>) -> NodeOptions {
108 self.parameter_set_action = Some(action);
109 self
110 }
111}
112
113impl Default for NodeOptions {
114 fn default() -> Self {
115 Self::new()
116 }
117}
118#[allow(clippy::large_enum_variant)] #[derive(Clone, Debug)]
124pub enum NodeEvent {
125 DDS(DomainParticipantStatusEvent),
126 ROS(ParticipantEntitiesInfo),
127}
128
129struct ParameterServers {
130 get_parameters_server: Server<rcl_interfaces::GetParametersService>,
131 get_parameter_types_server: Server<rcl_interfaces::GetParameterTypesService>,
132 list_parameters_server: Server<rcl_interfaces::ListParametersService>,
133 set_parameters_server: Server<rcl_interfaces::SetParametersService>,
134 set_parameters_atomically_server: Server<rcl_interfaces::SetParametersAtomicallyService>,
135 describe_parameters_server: Server<rcl_interfaces::DescribeParametersService>,
136}
137
138pub struct Spinner {
146 ros_context: Context,
147 stop_spin_receiver: async_channel::Receiver<()>,
148
149 readers_to_remote_writers: Arc<Mutex<BTreeMap<GUID, BTreeSet<GUID>>>>,
150 writers_to_remote_readers: Arc<Mutex<BTreeMap<GUID, BTreeSet<GUID>>>>,
151 external_nodes: Arc<Mutex<BTreeMap<Gid, Vec<NodeEntitiesInfo>>>>,
153 status_event_senders: Arc<Mutex<Vec<async_channel::Sender<NodeEvent>>>>,
155
156 use_sim_time: Arc<AtomicBool>,
157 sim_time: Arc<Mutex<ROSTime>>,
158 clock_topic: Topic,
159 allow_undeclared_parameters: bool,
160
161 parameter_servers: Option<ParameterServers>,
162 parameter_events_writer: Arc<Publisher<raw::ParameterEvent>>,
163 parameters: Arc<Mutex<BTreeMap<String, ParameterValue>>>,
164 parameter_validator: Option<Arc<Mutex<Box<ParameterFunc>>>>,
165 parameter_set_action: Option<Arc<Mutex<Box<ParameterFunc>>>>,
166 fully_qualified_node_name: String,
167}
168
169async fn next_if_some<S>(s: &mut Option<S>) -> S::Item
170where
171 S: Stream + Unpin + FusedStream,
172{
173 match s.as_mut() {
174 Some(stream) => stream.select_next_some().await,
175 None => std::future::pending().await,
176 }
177}
178
179impl Spinner {
180 pub async fn spin(self) -> CreateResult<()> {
181 info!("Starting Spinner for {}", self.fully_qualified_node_name);
182 let dds_status_listener = self.ros_context.domain_participant().status_listener();
183 let dds_status_stream = dds_status_listener.as_async_status_stream();
184 pin_mut!(dds_status_stream);
185
186 let ros_discovery_topic = self.ros_context.ros_discovery_topic();
187 let ros_discovery_reader = self
188 .ros_context
189 .create_subscription::<ParticipantEntitiesInfo>(&ros_discovery_topic, None)?;
190 let ros_discovery_stream = ros_discovery_reader.async_stream();
191 pin_mut!(ros_discovery_stream);
192
193 let ros_clock_reader = self
194 .ros_context
195 .create_subscription::<builtin_interfaces::Time>(&self.clock_topic, None)?;
196 let ros_clock_stream = ros_clock_reader.async_stream();
197 pin_mut!(ros_clock_stream);
198
199 let mut get_parameters_stream_opt = self
201 .parameter_servers
202 .as_ref()
203 .map(|s| s.get_parameters_server.receive_request_stream());
204 let mut get_parameter_types_stream_opt = self
205 .parameter_servers
206 .as_ref()
207 .map(|s| s.get_parameter_types_server.receive_request_stream());
208 let mut set_parameters_stream_opt = self
209 .parameter_servers
210 .as_ref()
211 .map(|s| s.set_parameters_server.receive_request_stream());
212 let mut set_parameters_atomically_stream_opt = self
213 .parameter_servers
214 .as_ref()
215 .map(|s| s.set_parameters_atomically_server.receive_request_stream());
216 let mut list_parameter_stream_opt = self
217 .parameter_servers
218 .as_ref()
219 .map(|s| s.list_parameters_server.receive_request_stream());
220 let mut describe_parameters_stream_opt = self
221 .parameter_servers
222 .as_ref()
223 .map(|s| s.describe_parameters_server.receive_request_stream());
224
225 info!("Spinner {} initialized", self.fully_qualified_node_name);
226
227 loop {
228 futures::select! {
229 _ = self.stop_spin_receiver.recv().fuse() => {
230 break;
231 }
232
233 clock_msg = ros_clock_stream.select_next_some() => {
234 match clock_msg {
235 Ok((time,_msg_info)) => {
236 *self.sim_time.lock().unwrap() = time.into();
239 }
240 Err(e) => warn!("Simulated clock receive error {e:?}")
241 }
242 }
243
244
245 get_parameters_request = next_if_some(&mut get_parameters_stream_opt).fuse() => {
246 match get_parameters_request {
247 Ok( (req_id, req) ) => {
248 info!("Get parameter request {req:?}");
249 let values = {
250 let param_db = self.parameters.lock().unwrap();
251 req.names.iter()
252 .map(|name| param_db.get(name.as_str())
253 .unwrap_or(&ParameterValue::NotSet))
254 .cloned()
255 .map( raw::ParameterValue::from)
256 .collect()
257 };
258 info!("Get parameters response: {values:?}");
259
260 self.parameter_servers.as_ref().unwrap().get_parameters_server
262 .async_send_response(req_id, rcl_interfaces::GetParametersResponse{ values })
263 .await
264 .unwrap_or_else(|e| warn!("GetParameter response error {e:?}"));
265 }
266 Err(e) => warn!("GetParameter request error {e:?}"),
267 }
268 }
269
270 get_parameter_types_request = next_if_some(&mut get_parameter_types_stream_opt).fuse() => {
271 match get_parameter_types_request {
272 Ok( (req_id, req) ) => {
273 warn!("Get parameter types request");
274 let values = {
275 let param_db = self.parameters.lock().unwrap();
276 req.names.iter()
277 .map(|name| param_db.get(name.as_str())
278 .unwrap_or(&ParameterValue::NotSet))
279 .map(ParameterValue::to_parameter_type_raw)
280 .collect()
281 };
282 info!("Get parameter types response: {values:?}");
283 self.parameter_servers.as_ref().unwrap().get_parameter_types_server
285 .async_send_response(req_id, rcl_interfaces::GetParameterTypesResponse{ values })
286 .await
287 .unwrap_or_else(|e| warn!("GetParameterTypes response error {e:?}"));
288 }
289 Err(e) => warn!("GetParameterTypes request error {e:?}"),
290 }
291 }
292
293 set_parameters_request = next_if_some(&mut set_parameters_stream_opt).fuse() => {
294 match set_parameters_request {
295 Ok( (req_id, req) ) => {
296 info!("Set parameter request {req:?}");
297 let results =
298 req.parameter.iter()
299 .cloned()
300 .map( Parameter::from ) .map( |Parameter{name, value}| self.set_parameter(&name,value))
302 .map(|r| r.into()) .collect();
304 info!("Set parameters response: {results:?}");
305 self.parameter_servers.as_ref().unwrap().set_parameters_server
307 .async_send_response(req_id, rcl_interfaces::SetParametersResponse{ results })
308 .await
309 .unwrap_or_else(|e| warn!("SetParameters response error {e:?}"));
310 }
311 Err(e) => warn!("SetParameters request error {e:?}"),
312 }
313 }
314
315 set_parameters_atomically_request = next_if_some(&mut set_parameters_atomically_stream_opt).fuse() => {
316 match set_parameters_atomically_request {
317 Ok( (req_id, req) ) => {
318 warn!("Set parameters atomically request {req:?}");
319 let results =
320 req.parameter.iter()
321 .cloned()
322 .map( Parameter::from ) .map( |Parameter{ .. } |
324 Err("Setting parameters atomically is not implemented.".to_owned())
326 )
327 .map(|r| r.into()) .collect();
329 warn!("Set parameters atomically response: {results:?}");
330 self.parameter_servers.as_ref().unwrap().set_parameters_atomically_server
332 .async_send_response(req_id, rcl_interfaces::SetParametersAtomicallyResponse{ results })
333 .await
334 .unwrap_or_else(|e| warn!("SetParameters response error {e:?}"));
335 }
336 Err(e) => warn!("SetParametersAtomically request error {e:?}"),
337 }
338 }
339
340 list_parameter_request = next_if_some(&mut list_parameter_stream_opt).fuse() => {
341 match list_parameter_request {
342 Ok( (req_id, req) ) => {
343 info!("List parameters request");
344 let prefixes = req.prefixes;
345 let names = {
348 let param_db = self.parameters.lock().unwrap();
349 param_db.keys()
350 .filter_map(|name|
351 if prefixes.is_empty() ||
352 prefixes.iter().any(|prefix| name.starts_with(prefix))
353 {
354 Some(name.clone())
355 } else { None }
356 )
357 .collect()
358 };
359 let result = rcl_interfaces::ListParametersResult{ names, prefixes: vec![] };
360 info!("List parameters response: {result:?}");
362 self.parameter_servers.as_ref().unwrap().list_parameters_server
363 .async_send_response(req_id, rcl_interfaces::ListParametersResponse{ result })
364 .await
365 .unwrap_or_else(|e| warn!("ListParameter response error {e:?}"));
366 }
367 Err(e) => warn!("ListParameter request error {e:?}"),
368 }
369 }
370
371 describe_parameters_request = next_if_some(&mut describe_parameters_stream_opt).fuse() => {
372 match describe_parameters_request {
373 Ok( (req_id, req) ) => {
374 info!("Describe parameters request {req:?}");
375 let values = {
376 let parameters = self.parameters.lock().unwrap();
377 req.names.iter()
378 .map( |name|
379 {
380 if let Some(value) = parameters.get(name) {
381 ParameterDescriptor::from_value(name, value)
382 } else {
383 ParameterDescriptor::unknown(name)
384 }
385 })
386 .map(|r| r.into()) .collect()
388 };
389 info!("Describe parameters response: {values:?}");
390 self.parameter_servers.as_ref().unwrap().describe_parameters_server
392 .async_send_response(req_id, rcl_interfaces::DescribeParametersResponse{ values })
393 .await
394 .unwrap_or_else(|e| warn!("DescribeParameters response error {e:?}"));
395 }
396 Err(e) => warn!("DescribeParameters request error {e:?}"),
397 }
398 }
399
400 participant_info_update = ros_discovery_stream.select_next_some() => {
401 match participant_info_update {
403 Ok((part_update, _msg_info)) => {
404 let mut info_map = self.external_nodes.lock().unwrap();
406 info_map.insert( part_update.gid, part_update.node_entities_info_seq.clone());
407 self.send_status_event( &NodeEvent::ROS(part_update) );
409 }
410 Err(e) => {
411 warn!("ros_discovery_info error {e:?}");
412 }
413 }
414 }
415
416 dp_status_event = dds_status_stream.select_next_some() => {
417 match dp_status_event {
421 DomainParticipantStatusEvent::RemoteReaderMatched { local_writer, remote_reader } => {
422 self.writers_to_remote_readers.lock().unwrap()
423 .entry(local_writer)
424 .and_modify(|s| {s.insert(remote_reader);} )
425 .or_insert(BTreeSet::from([remote_reader]));
426 }
427 DomainParticipantStatusEvent::RemoteWriterMatched { local_reader, remote_writer } => {
428 self.readers_to_remote_writers.lock().unwrap()
429 .entry(local_reader)
430 .and_modify(|s| {s.insert(remote_writer);} )
431 .or_insert(BTreeSet::from([remote_writer]));
432 }
433 DomainParticipantStatusEvent::ReaderLost {guid, ..} => {
434 for readers
435 in self.writers_to_remote_readers.lock().unwrap().values_mut() {
436 readers.remove(&guid);
437 }
438 }
439 DomainParticipantStatusEvent::WriterLost {guid, ..} => {
440 for writers
441 in self.readers_to_remote_writers.lock().unwrap().values_mut() {
442 writers.remove(&guid);
443 }
444 }
445
446 _ => {}
447 }
448
449 self.send_status_event( &NodeEvent::DDS(dp_status_event) );
451 }
452 }
453 }
454 info!("Spinner {} exiting .spin()", self.fully_qualified_node_name);
455 Ok(())
456 } fn send_status_event(&self, event: &NodeEvent) {
460 let mut closed = Vec::new();
461 let mut sender_array = self.status_event_senders.lock().unwrap();
462 for (i, sender) in sender_array.iter().enumerate() {
463 match sender.try_send(event.clone()) {
464 Ok(()) => {
465 }
467 Err(async_channel::TrySendError::Closed(_)) => {
468 closed.push(i) }
471 Err(e) => {
472 debug!("send_status_event: Send error for {i}: {e:?}");
473 }
476 }
477 }
478
479 for c in closed.iter().rev() {
481 sender_array.swap_remove(*c);
482 }
483 }
484
485 fn validate_parameter_on_set(&self, name: &str, value: &ParameterValue) -> SetParametersResult {
487 match name {
488 "use_sim_time" => match value {
490 ParameterValue::Boolean(_) => Ok(()),
491 _ => Err("Parameter'use_sim_time' must be Boolean.".to_owned()),
492 },
493 _ => {
495 match self.parameter_validator {
496 Some(ref v) => v.lock().unwrap()(name, value), None => Ok(()), }
499 }
500 }
501 }
502
503 fn execute_parameter_set_actions(
505 &self,
506 name: &str,
507 value: &ParameterValue,
508 ) -> SetParametersResult {
509 match name {
510 "use_sim_time" => match value {
511 ParameterValue::Boolean(s) => {
512 self.use_sim_time.store(*s, Ordering::SeqCst);
513 Ok(())
514 }
515 _ => Err("Parameter 'use_sim_time' must be Boolean.".to_owned()),
516 },
517 _ => {
518 match self.parameter_set_action {
519 Some(ref v) => v.lock().unwrap()(name, value), None => Ok(()), }
522 }
523 }
524 }
525
526 pub fn set_parameter(&self, name: &str, value: ParameterValue) -> Result<(), String> {
529 let already_set = self.parameters.lock().unwrap().contains_key(name);
530 if self.allow_undeclared_parameters || already_set {
531 self.validate_parameter_on_set(name, &value)?;
532 self.execute_parameter_set_actions(name, &value)?;
533
534 let p = raw::Parameter {
536 name: name.to_string(),
537 value: value.clone().into(),
538 };
539 let (new_parameters, changed_parameters) = if already_set {
540 (vec![], vec![p])
541 } else {
542 (vec![p], vec![])
543 };
544
545 self
547 .parameters
548 .lock()
549 .unwrap()
550 .insert(name.to_owned(), value);
551 self
553 .parameter_events_writer
554 .publish(raw::ParameterEvent {
555 timestamp: rustdds::Timestamp::now(), node: self.fully_qualified_node_name.clone(),
557 new_parameters,
558 changed_parameters,
559 deleted_parameters: vec![],
560 })
561 .unwrap_or_else(|e| warn!("undeclare_parameter: {e:?}"));
562 Ok(())
563 } else {
564 Err("Setting undeclared parameter '".to_owned() + name + "' is not allowed.")
565 }
566 }
567} #[derive(Debug)]
574pub enum NodeCreateError {
575 DDS(CreateError),
576 BadParameter(String),
577}
578
579impl From<CreateError> for NodeCreateError {
580 fn from(c: CreateError) -> NodeCreateError {
581 NodeCreateError::DDS(c)
582 }
583}
584
585impl fmt::Display for NodeCreateError {
586 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
587 match self {
588 Self::DDS(create_error) => write!(f, "NodeCreateError::DDS : {create_error}"),
589 Self::BadParameter(s) => write!(f, "NodeCreateError::BadParameter : {s}"),
590 }
591 }
592}
593
594impl Error for NodeCreateError {
595 fn source(&self) -> Option<&(dyn Error + 'static)> {
596 match self {
597 Self::DDS(create_error) => Some(create_error),
598 Self::BadParameter(_) => None,
599 }
600 }
601}
602
603pub enum ParameterError {
605 AlreadyDeclared,
606 InvalidName,
607}
608
609pub struct Node {
623 node_name: NodeName,
624 options: NodeOptions,
625
626 pub(crate) ros_context: Context,
627
628 readers: BTreeSet<Gid>,
631 writers: BTreeSet<Gid>,
632
633 suppress_node_info_updates: Arc<AtomicBool>,
634 readers_to_remote_writers: Arc<Mutex<BTreeMap<GUID, BTreeSet<GUID>>>>,
641 writers_to_remote_readers: Arc<Mutex<BTreeMap<GUID, BTreeSet<GUID>>>>,
642
643 external_nodes: Arc<Mutex<BTreeMap<Gid, Vec<NodeEntitiesInfo>>>>,
645 stop_spin_sender: Option<async_channel::Sender<()>>,
646
647 status_event_senders: Arc<Mutex<Vec<async_channel::Sender<NodeEvent>>>>,
649
650 rosout_writer: Arc<Option<Publisher<Log>>>,
652 rosout_reader: Option<Subscription<Log>>,
653
654 parameter_events_writer: Arc<Publisher<raw::ParameterEvent>>,
657
658 parameters: Arc<Mutex<BTreeMap<String, ParameterValue>>>,
660 parameter_validator: Option<Arc<Mutex<Box<ParameterFunc>>>>,
662 parameter_set_action: Option<Arc<Mutex<Box<ParameterFunc>>>>,
663
664 use_sim_time: Arc<AtomicBool>,
666 sim_time: Arc<Mutex<ROSTime>>,
667}
668
669impl Node {
670 pub(crate) fn new(
671 node_name: NodeName,
672 mut options: NodeOptions,
673 ros_context: Context,
674 ) -> Result<Node, NodeCreateError> {
675 let paramtopic = ros_context.get_parameter_events_topic();
676 let rosout_topic = ros_context.get_rosout_topic();
677
678 let enable_rosout = options.enable_rosout;
679 let rosout_reader = options.enable_rosout_reading;
680
681 let parameter_events_writer = ros_context.create_publisher(¶mtopic, None)?;
682
683 options.declared_parameters.push(Parameter {
686 name: "use_sim_time".to_string(),
687 value: ParameterValue::Boolean(false),
688 });
689 let parameters = options
690 .declared_parameters
691 .iter()
692 .cloned()
693 .map(|Parameter { name, value }| (name, value))
694 .collect::<BTreeMap<String, ParameterValue>>();
695
696 let parameter_validator = options
697 .parameter_validator
698 .take()
699 .map(|b| Arc::new(Mutex::new(b)));
700 let parameter_set_action = options
701 .parameter_set_action
702 .take()
703 .map(|b| Arc::new(Mutex::new(b)));
704
705 let mut node = Node {
706 node_name,
707 options,
708 ros_context,
709 readers: BTreeSet::new(),
710 writers: BTreeSet::new(),
711 readers_to_remote_writers: Arc::new(Mutex::new(BTreeMap::new())),
712 writers_to_remote_readers: Arc::new(Mutex::new(BTreeMap::new())),
713 external_nodes: Arc::new(Mutex::new(BTreeMap::new())),
714 suppress_node_info_updates: Arc::new(AtomicBool::new(false)),
715 stop_spin_sender: None,
716 status_event_senders: Arc::new(Mutex::new(Vec::new())),
717 rosout_writer: Arc::new(None), rosout_reader: None,
719 parameter_events_writer: Arc::new(parameter_events_writer),
720 parameters: Arc::new(Mutex::new(parameters)),
721 parameter_validator,
722 parameter_set_action,
723 use_sim_time: Arc::new(AtomicBool::new(false)),
724 sim_time: Arc::new(Mutex::new(ROSTime::ZERO)),
725 };
726
727 node.suppress_node_info_updates(true);
728
729 node.rosout_writer = if enable_rosout {
730 Arc::new(Some(
731 node.create_publisher(&rosout_topic, None)?,
733 ))
734 } else {
735 Arc::new(None) };
737 node.rosout_reader = if rosout_reader {
738 Some(node.create_subscription(&rosout_topic, None)?)
739 } else {
740 None
741 };
742
743 node
745 .parameters
746 .lock()
747 .unwrap()
748 .iter()
749 .try_for_each(|(name, value)| {
750 node.validate_parameter_on_set(name, value)?;
751 node.execute_parameter_set_actions(name, value)?;
752 Ok(())
753 })
754 .map_err(NodeCreateError::BadParameter)?;
755
756 node.suppress_node_info_updates(false);
757
758 Ok(node)
759 }
760
761 pub fn time_now(&self) -> ROSTime {
765 if self.use_sim_time.load(Ordering::SeqCst) {
766 *self.sim_time.lock().unwrap()
767 } else {
768 ROSTime::now()
769 }
770 }
771
772 pub fn time_now_not_simulated(&self) -> ROSTime {
773 ROSTime::now()
774 }
775
776 pub fn spinner(&mut self) -> CreateResult<Spinner> {
785 if self.stop_spin_sender.is_some() {
786 panic!("Attempted to crate a second spinner.");
787 }
788 let (stop_spin_sender, stop_spin_receiver) = async_channel::bounded(1);
789 self.stop_spin_sender = Some(stop_spin_sender);
790
791 let service_qos = QosPolicyBuilder::new()
793 .reliability(policy::Reliability::Reliable {
794 max_blocking_time: Duration::from_millis(100),
795 })
796 .history(policy::History::KeepLast { depth: 1 })
797 .build();
798
799 let node_name = self.node_name.fully_qualified_name();
800
801 self.suppress_node_info_updates(true);
802
803 let parameter_servers = if self.options.start_parameter_services {
804 let service_mapping = ServiceMapping::Enhanced; let get_parameters_server = self.create_server(
806 service_mapping,
807 &Name::new(&node_name, "get_parameters").unwrap(),
808 &ServiceTypeName::new("rcl_interfaces", "GetParameters"),
809 service_qos.clone(),
810 service_qos.clone(),
811 )?;
812 let get_parameter_types_server = self.create_server(
813 service_mapping,
814 &Name::new(&node_name, "get_parameter_types").unwrap(),
815 &ServiceTypeName::new("rcl_interfaces", "GetParameterTypes"),
816 service_qos.clone(),
817 service_qos.clone(),
818 )?;
819 let set_parameters_server = self.create_server(
820 service_mapping,
821 &Name::new(&node_name, "set_parameters").unwrap(),
822 &ServiceTypeName::new("rcl_interfaces", "SetParameters"),
823 service_qos.clone(),
824 service_qos.clone(),
825 )?;
826 let set_parameters_atomically_server = self.create_server(
827 service_mapping,
828 &Name::new(&node_name, "set_parameters_atomically").unwrap(),
829 &ServiceTypeName::new("rcl_interfaces", "SetParametersAtomically"),
830 service_qos.clone(),
831 service_qos.clone(),
832 )?;
833 let list_parameters_server = self.create_server(
834 service_mapping,
835 &Name::new(&node_name, "list_parameters").unwrap(),
836 &ServiceTypeName::new("rcl_interfaces", "ListParameters"),
837 service_qos.clone(),
838 service_qos.clone(),
839 )?;
840 let describe_parameters_server = self.create_server(
841 service_mapping,
842 &Name::new(&node_name, "describe_parameters").unwrap(),
843 &ServiceTypeName::new("rcl_interfaces", "DescribeParameters"),
844 service_qos.clone(),
845 service_qos.clone(),
846 )?;
847
848 Some(ParameterServers {
849 get_parameters_server,
850 get_parameter_types_server,
851 list_parameters_server,
852 set_parameters_server,
853 set_parameters_atomically_server,
854 describe_parameters_server,
855 })
856 } else {
857 None };
859
860 let clock_topic = self.create_topic(
861 &Name::new("/", "clock").unwrap(),
862 MessageTypeName::new("builtin_interfaces", "Time"),
863 &DEFAULT_SUBSCRIPTION_QOS,
864 )?;
865
866 self.suppress_node_info_updates(false);
867
868 Ok(Spinner {
869 ros_context: self.ros_context.clone(),
870 stop_spin_receiver,
871 readers_to_remote_writers: Arc::clone(&self.readers_to_remote_writers),
872 writers_to_remote_readers: Arc::clone(&self.writers_to_remote_readers),
873 external_nodes: Arc::clone(&self.external_nodes),
874 status_event_senders: Arc::clone(&self.status_event_senders),
875 use_sim_time: Arc::clone(&self.use_sim_time),
876 sim_time: Arc::clone(&self.sim_time),
877 clock_topic,
878 parameter_servers,
879 parameter_events_writer: Arc::clone(&self.parameter_events_writer),
880 parameters: Arc::clone(&self.parameters),
881 allow_undeclared_parameters: self.options.allow_undeclared_parameters,
882 parameter_validator: self.parameter_validator.as_ref().map(Arc::clone),
883 parameter_set_action: self.parameter_set_action.as_ref().map(Arc::clone),
884 fully_qualified_node_name: self.fully_qualified_name(),
885 })
886 }
887
888 pub fn have_spinner(&self) -> bool {
893 self.stop_spin_sender.is_some()
894 }
895
896 fn generate_node_info(&self) -> NodeEntitiesInfo {
898 let mut node_info = NodeEntitiesInfo::new(self.node_name.clone());
899
900 node_info.add_writer(Gid::from(self.parameter_events_writer.guid()));
901 if let Some(ref row) = *self.rosout_writer {
902 node_info.add_writer(Gid::from(row.guid()));
903 }
904
905 for reader in &self.readers {
906 node_info.add_reader(*reader);
907 }
908
909 for writer in &self.writers {
910 node_info.add_writer(*writer);
911 }
912
913 node_info
914 }
915
916 fn suppress_node_info_updates(&mut self, suppress: bool) {
917 self
918 .suppress_node_info_updates
919 .store(suppress, Ordering::SeqCst);
920
921 if !suppress {
923 self.ros_context.update_node(self.generate_node_info());
924 }
925 }
926
927 fn add_reader(&mut self, reader: Gid) {
928 self.readers.insert(reader);
929 if !self.suppress_node_info_updates.load(Ordering::SeqCst) {
930 self.ros_context.update_node(self.generate_node_info());
931 }
932 }
933
934 fn add_writer(&mut self, writer: Gid) {
935 self.writers.insert(writer);
936 if !self.suppress_node_info_updates.load(Ordering::SeqCst) {
937 self.ros_context.update_node(self.generate_node_info());
938 }
939 }
940
941 pub fn namespace(&self) -> &str {
942 self.node_name.namespace()
943 }
944
945 pub fn fully_qualified_name(&self) -> String {
946 self.node_name.fully_qualified_name()
947 }
948
949 pub fn options(&self) -> &NodeOptions {
950 &self.options
951 }
952
953 pub fn domain_id(&self) -> u16 {
954 self.ros_context.domain_id()
955 }
956
957 pub fn undeclare_parameter(&self, name: &str) {
961 let prev_value = self.parameters.lock().unwrap().remove(name);
962
963 if let Some(deleted_param) = prev_value {
964 self
966 .parameter_events_writer
967 .publish(raw::ParameterEvent {
968 timestamp: self.time_now().into(),
969 node: self.fully_qualified_name(),
970 new_parameters: vec![],
971 changed_parameters: vec![],
972 deleted_parameters: vec![raw::Parameter {
973 name: name.to_string(),
974 value: deleted_param.into(),
975 }],
976 })
977 .unwrap_or_else(|e| warn!("undeclare_parameter: {e:?}"));
978 }
979 }
980
981 pub fn has_parameter(&self, name: &str) -> bool {
983 self.parameters.lock().unwrap().contains_key(name)
984 }
985
986 pub fn set_parameter(&self, name: &str, value: ParameterValue) -> Result<(), String> {
997 let already_set = self.parameters.lock().unwrap().contains_key(name);
998 if self.options.allow_undeclared_parameters || already_set {
999 self.validate_parameter_on_set(name, &value)?;
1000 self.execute_parameter_set_actions(name, &value)?;
1001
1002 let p = raw::Parameter {
1004 name: name.to_string(),
1005 value: value.clone().into(),
1006 };
1007 let (new_parameters, changed_parameters) = if already_set {
1008 (vec![], vec![p])
1009 } else {
1010 (vec![p], vec![])
1011 };
1012
1013 self
1015 .parameters
1016 .lock()
1017 .unwrap()
1018 .insert(name.to_owned(), value);
1019 self
1021 .parameter_events_writer
1022 .publish(raw::ParameterEvent {
1023 timestamp: self.time_now().into(),
1024 node: self.fully_qualified_name(),
1025 new_parameters,
1026 changed_parameters,
1027 deleted_parameters: vec![],
1028 })
1029 .unwrap_or_else(|e| warn!("undeclare_parameter: {e:?}"));
1030 Ok(())
1031 } else {
1032 Err("Setting undeclared parameter '".to_owned() + name + "' is not allowed.")
1033 }
1034 }
1035
1036 pub fn allow_undeclared_parameters(&self) -> bool {
1037 self.options.allow_undeclared_parameters
1038 }
1039
1040 pub fn get_parameter(&self, name: &str) -> Option<ParameterValue> {
1042 self
1043 .parameters
1044 .lock()
1045 .unwrap()
1046 .get(name)
1047 .map(|p| p.to_owned())
1048 }
1049
1050 pub fn list_parameters(&self) -> Vec<String> {
1051 self
1052 .parameters
1053 .lock()
1054 .unwrap()
1055 .keys()
1056 .map(move |k| k.to_owned())
1057 .collect::<Vec<_>>()
1058 }
1059
1060 fn validate_parameter_on_set(&self, name: &str, value: &ParameterValue) -> SetParametersResult {
1067 match name {
1068 "use_sim_time" => match value {
1070 ParameterValue::Boolean(_) => Ok(()),
1071 _ => Err("Parameter'use_sim_time' must be Boolean.".to_owned()),
1072 },
1073 _ => {
1075 match self.parameter_validator {
1076 Some(ref v) => v.lock().unwrap()(name, value), None => Ok(()), }
1079 }
1080 }
1081 }
1082
1083 fn execute_parameter_set_actions(
1085 &self,
1086 name: &str,
1087 value: &ParameterValue,
1088 ) -> SetParametersResult {
1089 match name {
1090 "use_sim_time" => match value {
1091 ParameterValue::Boolean(s) => {
1092 self.use_sim_time.store(*s, Ordering::SeqCst);
1093 Ok(())
1094 }
1095 _ => Err("Parameter 'use_sim_time' must be Boolean.".to_owned()),
1096 },
1097 _ => {
1098 match self.parameter_set_action {
1099 Some(ref v) => v.lock().unwrap()(name, value), None => Ok(()), }
1102 }
1103 }
1104 }
1105
1106 pub fn status_receiver(&self) -> Receiver<NodeEvent> {
1113 if self.have_spinner() {
1114 let (status_event_sender, status_event_receiver) = async_channel::bounded(8);
1115 self
1116 .status_event_senders
1117 .lock()
1118 .unwrap()
1119 .push(status_event_sender);
1120 status_event_receiver
1121 } else {
1122 panic!("status_receiver() cannot set up a receiver, because no Spinner is running.")
1123 }
1124 }
1125
1126 pub(crate) fn wait_for_writer(&self, reader: GUID) -> impl Future<Output = ()> {
1128 let status_receiver = self.status_receiver();
1130
1131 let already_present = self
1132 .readers_to_remote_writers
1133 .lock()
1134 .unwrap()
1135 .get(&reader)
1136 .map(|writers| !writers.is_empty()) .unwrap_or(false); if already_present {
1140 WriterWait::Ready
1141 } else {
1142 WriterWait::Wait {
1143 this_reader: reader,
1144 status_event_stream: Box::pin(status_receiver),
1145 }
1146 }
1147 }
1148
1149 pub(crate) fn wait_for_reader(&self, writer: GUID) -> impl Future<Output = ()> {
1150 let status_receiver = self.status_receiver();
1152
1153 let already_present = self
1154 .writers_to_remote_readers
1155 .lock()
1156 .unwrap()
1157 .get(&writer)
1158 .map(|readers| !readers.is_empty()) .unwrap_or(false); if already_present {
1165 info!("wait_for_reader: Already have matched a reader.");
1166 ReaderWait::Ready
1167 } else {
1168 ReaderWait::Wait {
1169 this_writer: writer,
1170 status_event_stream: Box::pin(status_receiver),
1171 }
1172 }
1173 }
1174
1175 pub(crate) fn get_publisher_count(&self, subscription_guid: GUID) -> usize {
1176 self
1177 .readers_to_remote_writers
1178 .lock()
1179 .unwrap()
1180 .get(&subscription_guid)
1181 .map(BTreeSet::len)
1182 .unwrap_or_else(|| {
1183 error!("get_publisher_count: Subscriber {subscription_guid:?} not known to node.");
1184 0
1185 })
1186 }
1187
1188 pub(crate) fn get_subscription_count(&self, publisher_guid: GUID) -> usize {
1189 self
1190 .writers_to_remote_readers
1191 .lock()
1192 .unwrap()
1193 .get(&publisher_guid)
1194 .map(BTreeSet::len)
1195 .unwrap_or_else(|| {
1196 error!("get_subscription_count: Publisher {publisher_guid:?} not known to node.");
1197 0
1198 })
1199 }
1200
1201 pub fn rosout_subscription(&self) -> Option<&Subscription<Log>> {
1205 self.rosout_reader.as_ref()
1206 }
1207
1208 pub fn create_topic(
1237 &self,
1238 topic_name: &Name,
1239 type_name: MessageTypeName,
1240 qos: &QosPolicies,
1241 ) -> CreateResult<Topic> {
1242 let dds_name = topic_name.to_dds_name("rt", &self.node_name, "");
1243 self.ros_context.create_topic(dds_name, type_name, qos)
1244 }
1245
1246 pub fn create_subscription<D: 'static>(
1254 &mut self,
1255 topic: &Topic,
1256 qos: Option<QosPolicies>,
1257 ) -> CreateResult<Subscription<D>> {
1258 let sub = self.ros_context.create_subscription(topic, qos)?;
1259 self.add_reader(sub.guid().into());
1260 Ok(sub)
1261 }
1262
1263 pub fn create_publisher<D: Serialize>(
1272 &mut self,
1273 topic: &Topic,
1274 qos: Option<QosPolicies>,
1275 ) -> CreateResult<Publisher<D>> {
1276 let p = self.ros_context.create_publisher(topic, qos)?;
1277 self.add_writer(p.guid().into());
1278 Ok(p)
1279 }
1280
1281 pub(crate) fn create_simpledatareader<D, DA>(
1282 &mut self,
1283 topic: &Topic,
1284 qos: Option<QosPolicies>,
1285 ) -> CreateResult<no_key::SimpleDataReader<D, DA>>
1286 where
1287 D: 'static,
1288 DA: rustdds::no_key::DeserializerAdapter<D> + 'static,
1289 {
1290 let r = self.ros_context.create_simpledatareader(topic, qos)?;
1291 self.add_reader(r.guid().into());
1292 Ok(r)
1293 }
1294
1295 pub(crate) fn create_datawriter<D, SA>(
1296 &mut self,
1297 topic: &Topic,
1298 qos: Option<QosPolicies>,
1299 ) -> CreateResult<no_key::DataWriter<D, SA>>
1300 where
1301 SA: rustdds::no_key::SerializerAdapter<D>,
1302 {
1303 let w = self.ros_context.create_datawriter(topic, qos)?;
1304 self.add_writer(w.guid().into());
1305 Ok(w)
1306 }
1307
1308 pub fn create_client<S>(
1316 &mut self,
1317 service_mapping: ServiceMapping,
1318 service_name: &Name,
1319 service_type_name: &ServiceTypeName,
1320 request_qos: QosPolicies,
1321 response_qos: QosPolicies,
1322 ) -> CreateResult<Client<S>>
1323 where
1324 S: Service + 'static,
1325 S::Request: Clone,
1326 {
1327 let rq_topic = self.ros_context.domain_participant().create_topic(
1333 service_name.to_dds_name("rq", &self.node_name, "Request"),
1334 service_type_name.dds_request_type(),
1336 &request_qos,
1337 TopicKind::NoKey,
1338 )?;
1339 let rs_topic = self.ros_context.domain_participant().create_topic(
1340 service_name.to_dds_name("rr", &self.node_name, "Reply"),
1341 service_type_name.dds_response_type(),
1343 &response_qos,
1344 TopicKind::NoKey,
1345 )?;
1346
1347 let c = Client::<S>::new(
1348 service_mapping,
1349 self,
1350 &rq_topic,
1351 &rs_topic,
1352 Some(request_qos),
1353 Some(response_qos),
1354 )?;
1355
1356 Ok(c)
1357 }
1358
1359 pub fn create_server<S>(
1368 &mut self,
1369 service_mapping: ServiceMapping,
1370 service_name: &Name,
1371 service_type_name: &ServiceTypeName,
1372 request_qos: QosPolicies,
1373 response_qos: QosPolicies,
1374 ) -> CreateResult<Server<S>>
1375 where
1376 S: Service + 'static,
1377 S::Request: Clone,
1378 {
1379 let rq_topic = self.ros_context.domain_participant().create_topic(
1385 service_name.to_dds_name("rq", &self.node_name, "Request"),
1387 service_type_name.dds_request_type(),
1388 &request_qos,
1389 TopicKind::NoKey,
1390 )?;
1391 let rs_topic = self.ros_context.domain_participant().create_topic(
1392 service_name.to_dds_name("rr", &self.node_name, "Reply"),
1393 service_type_name.dds_response_type(),
1394 &response_qos,
1395 TopicKind::NoKey,
1396 )?;
1397
1398 let s = Server::<S>::new(
1399 service_mapping,
1400 self,
1401 &rq_topic,
1402 &rs_topic,
1403 Some(request_qos),
1404 Some(response_qos),
1405 )?;
1406
1407 Ok(s)
1408 }
1409
1410 pub fn create_action_client<A>(
1411 &mut self,
1412 service_mapping: ServiceMapping,
1413 action_name: &Name,
1414 action_type_name: &ActionTypeName,
1415 action_qos: ActionClientQosPolicies,
1416 ) -> CreateResult<ActionClient<A>>
1417 where
1418 A: ActionTypes + 'static,
1419 {
1420 let services_base_name = action_name.push("_action");
1423
1424 let goal_service_type = action_type_name.dds_action_service("_SendGoal");
1426 let my_goal_client = self.create_client(
1427 service_mapping,
1428 &services_base_name.push("send_goal"),
1430 &goal_service_type,
1431 action_qos.goal_service.clone(),
1432 action_qos.goal_service,
1433 )?;
1434
1435 let cancel_goal_type = ServiceTypeName::new("action_msgs", "CancelGoal");
1437 let my_cancel_client = self.create_client(
1438 service_mapping,
1439 &services_base_name.push("cancel_goal"),
1441 &cancel_goal_type,
1442 action_qos.cancel_service.clone(),
1443 action_qos.cancel_service,
1444 )?;
1445
1446 let result_service_type = action_type_name.dds_action_service("_GetResult");
1448 let my_result_client = self.create_client(
1449 service_mapping,
1450 &services_base_name.push("get_result"),
1452 &result_service_type,
1453 action_qos.result_service.clone(),
1454 action_qos.result_service,
1455 )?;
1456
1457 let action_topic_namespace = action_name.push("_action");
1458
1459 let feedback_topic_type = action_type_name.dds_action_topic("_FeedbackMessage");
1460 let feedback_topic = self.create_topic(
1461 &action_topic_namespace.push("feedback"),
1462 feedback_topic_type,
1463 &action_qos.feedback_subscription,
1464 )?;
1465 let my_feedback_subscription =
1466 self.create_subscription(&feedback_topic, Some(action_qos.feedback_subscription))?;
1467
1468 let status_topic = self.create_topic(
1470 &action_topic_namespace.push("status"),
1471 MessageTypeName::new("action_msgs", "GoalStatusArray"),
1472 &action_qos.status_subscription,
1473 )?;
1474 let my_status_subscription =
1475 self.create_subscription(&status_topic, Some(action_qos.status_subscription))?;
1476
1477 Ok(ActionClient {
1478 my_goal_client,
1479 my_cancel_client,
1480 my_result_client,
1481 my_feedback_subscription,
1482 my_status_subscription,
1483 my_action_name: action_name.clone(),
1484 })
1485 }
1486
1487 pub fn create_action_server<A>(
1488 &mut self,
1489 service_mapping: ServiceMapping,
1490 action_name: &Name,
1491 action_type_name: &ActionTypeName,
1492 action_qos: ActionServerQosPolicies,
1493 ) -> CreateResult<ActionServer<A>>
1494 where
1495 A: ActionTypes + 'static,
1496 {
1497 let services_base_name = action_name.push("_action");
1498
1499 let goal_service_type = action_type_name.dds_action_service("_SendGoal");
1501 let my_goal_server = self.create_server(
1502 service_mapping,
1503 &services_base_name.push("send_goal"),
1505 &goal_service_type,
1506 action_qos.goal_service.clone(),
1507 action_qos.goal_service,
1508 )?;
1509
1510 let cancel_service_type = ServiceTypeName::new("action_msgs", "CancelGoal");
1512 let my_cancel_server = self.create_server(
1513 service_mapping,
1514 &services_base_name.push("cancel_goal"),
1516 &cancel_service_type,
1517 action_qos.cancel_service.clone(),
1518 action_qos.cancel_service,
1519 )?;
1520
1521 let result_service_type = action_type_name.dds_action_service("_GetResult");
1523 let my_result_server = self.create_server(
1524 service_mapping,
1525 &services_base_name.push("get_result"),
1527 &result_service_type,
1528 action_qos.result_service.clone(),
1529 action_qos.result_service,
1530 )?;
1531
1532 let action_topic_namespace = action_name.push("_action");
1533
1534 let feedback_topic_type = action_type_name.dds_action_topic("_FeedbackMessage");
1535 let feedback_topic = self.create_topic(
1536 &action_topic_namespace.push("feedback"),
1537 feedback_topic_type,
1538 &action_qos.feedback_publisher,
1539 )?;
1540 let my_feedback_publisher =
1541 self.create_publisher(&feedback_topic, Some(action_qos.feedback_publisher))?;
1542
1543 let status_topic_type = MessageTypeName::new("action_msgs", "GoalStatusArray");
1544 let status_topic = self.create_topic(
1545 &action_topic_namespace.push("status"),
1546 status_topic_type,
1547 &action_qos.status_publisher,
1548 )?;
1549 let my_status_publisher =
1550 self.create_publisher(&status_topic, Some(action_qos.status_publisher))?;
1551
1552 Ok(ActionServer {
1553 my_goal_server,
1554 my_cancel_server,
1555 my_result_server,
1556 my_feedback_publisher,
1557 my_status_publisher,
1558 my_action_name: action_name.clone(),
1559 })
1560 }
1561
1562 pub fn logging_handle(&self) -> NodeLoggingHandle {
1566 NodeLoggingHandle {
1567 rosout_writer: Arc::clone(&self.rosout_writer),
1568 base_name: self.node_name.base_name().to_string(),
1569 }
1570 }
1571
1572 pub fn stop_spinner(&self) {
1573 info!("Signalling spinner to stop (manual)");
1574 if let Some(ref stop_spin_sender) = self.stop_spin_sender {
1575 stop_spin_sender
1576 .try_send(())
1577 .unwrap_or_else(|e| error!("Cannot notify spin task to stop: {e:?}"));
1578 }
1579 }
1580} impl Drop for Node {
1583 fn drop(&mut self) {
1584 debug!("Signalling spinner to stop (.drop)");
1585 if let Some(ref stop_spin_sender) = self.stop_spin_sender {
1586 stop_spin_sender
1587 .try_send(())
1588 .unwrap_or_else(|e| error!("Cannot notify spin task to stop: {e:?}"));
1589 }
1590
1591 self
1592 .ros_context
1593 .remove_node(self.fully_qualified_name().as_str());
1594 }
1595}
1596
1597impl RosoutRaw for Node {
1598 fn rosout_writer(&self) -> Arc<Option<Publisher<Log>>> {
1599 Arc::clone(&self.rosout_writer)
1600 }
1601
1602 fn base_name(&self) -> &str {
1603 self.node_name.base_name()
1604 }
1605}
1606
1607#[macro_export]
1626macro_rules! rosout {
1627 ($node:expr, $lvl:expr, $($arg:tt)+) => (
1628 $crate::rosout::RosoutRaw::rosout_raw(
1629 &$node,
1630 $crate::ros2::Timestamp::now(),
1631 $lvl,
1632 $crate::rosout::RosoutRaw::base_name(&$node),
1633 &std::format!($($arg)+), std::file!(),
1635 "<unknown_func>", std::line!(),
1637 );
1638 );
1639}
1640
1641#[must_use = "futures do nothing unless you `.await` or poll them"]
1649pub enum ReaderWait<'a> {
1650 Wait {
1652 this_writer: GUID, status_event_stream: stream::BoxStream<'a, NodeEvent>,
1654 },
1655 Ready,
1657}
1658
1659impl Future for ReaderWait<'_> {
1660 type Output = ();
1661
1662 fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
1663 match *self {
1664 ReaderWait::Ready => Poll::Ready(()),
1665
1666 ReaderWait::Wait {
1667 this_writer,
1668 ref mut status_event_stream,
1669 } => {
1670 debug!("wait_for_reader: Waiting for a reader.");
1671 loop {
1672 match status_event_stream.poll_next_unpin(cx) {
1673 Poll::Ready(Some(NodeEvent::DDS(
1675 DomainParticipantStatusEvent::RemoteReaderMatched {
1676 local_writer,
1677 remote_reader,
1678 },
1679 )))
1680 if local_writer == this_writer =>
1681 {
1682 debug!("wait_for_reader: Matched remote reader {remote_reader:?}.");
1683 return Poll::Ready(());
1684 }
1685
1686 Poll::Ready(_) => {
1687 debug!("wait_for_reader: other event. Continue polling.");
1689 }
1691
1692 Poll::Pending => return Poll::Pending,
1693 }
1694 }
1695 }
1696 }
1697 }
1698}
1699
1700#[must_use = "futures do nothing unless you `.await` or poll them"]
1707pub enum WriterWait<'a> {
1708 Wait {
1710 this_reader: GUID,
1711 status_event_stream: stream::BoxStream<'a, NodeEvent>,
1712 },
1713 Ready,
1715}
1716
1717impl Future for WriterWait<'_> {
1718 type Output = ();
1719
1720 fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
1721 match *self {
1722 WriterWait::Ready => Poll::Ready(()),
1723
1724 WriterWait::Wait {
1725 this_reader,
1726 ref mut status_event_stream,
1727 } => {
1728 debug!("wait_for_writer: Waiting for a writer.");
1729 loop {
1730 match status_event_stream.poll_next_unpin(cx) {
1734 Poll::Ready(Some(NodeEvent::DDS(
1736 DomainParticipantStatusEvent::RemoteWriterMatched {
1737 local_reader,
1738 remote_writer,
1739 },
1740 )))
1741 if local_reader == this_reader =>
1742 {
1743 debug!("wait_for_writer: Matched remote writer {remote_writer:?}.");
1744 return Poll::Ready(());
1745 }
1746
1747 Poll::Ready(_) => {
1748 trace!("=== other writer. Continue polling.");
1750 }
1752
1753 Poll::Pending => return Poll::Pending,
1754 }
1755 }
1756 }
1757 }
1758 }
1759}
1760
1761#[cfg(test)]
1762mod tests {
1763 use crate::Context;
1764 use super::{Node, NodeName, NodeOptions};
1765
1766 #[test]
1767 fn node_is_sync() {
1768 let node = Node::new(
1769 NodeName::new("/", "base_name").unwrap(),
1770 NodeOptions::new(),
1771 Context::new().unwrap(),
1772 )
1773 .unwrap();
1774
1775 fn requires_send_sync<T: Send + Sync>(_t: T) {}
1776 requires_send_sync(node);
1777 }
1778}