rustdds/dds/
helpers.rs

1use std::thread;
2
3use mio_extras::channel::{SyncSender, TrySendError};
4
5use crate::structure::duration::Duration;
6
7const TIMEOUT_EPSILON_NS: i64 = 1000; // 1µs
8
9// By default, give background thread 20 ms to react
10pub const TIMEOUT_FALLBACK: Duration = Duration::from_nanos(20_000_000); // 20 ms
11
12pub fn try_send_timeout<T>(
13  sender: &SyncSender<T>,
14  t: T,
15  timeout_opt: Option<Duration>,
16) -> Result<(), TrySendError<T>> {
17  match sender.try_send(t) {
18    Ok(()) => Ok(()), // This is expected to be the common case
19
20    Err(TrySendError::Full(tt)) => {
21      let mut mt = tt;
22      let timeout = timeout_opt.unwrap_or(TIMEOUT_FALLBACK).to_nanoseconds();
23      let mut time_left = timeout;
24      let mut delay = TIMEOUT_EPSILON_NS;
25      while time_left > TIMEOUT_EPSILON_NS {
26        match sender.try_send(mt) {
27          Ok(()) => return Ok(()),
28          Err(TrySendError::Full(tt)) => {
29            thread::sleep(std::time::Duration::from_nanos(delay as u64)); // and try again
30            mt = tt;
31            time_left -= delay;
32            delay *= 2;
33          }
34          Err(other) => return Err(other),
35        }
36      }
37      Err(TrySendError::Full(mt))
38    }
39    Err(other) => Err(other),
40  }
41}