Skip to main content

sync_oneshot/
lib.rs

1//! A minimal oneshot channel for synchronous Rust.
2//!
3//! A oneshot channel is used for sending a single message between threads.
4//! The [`channel`] function is used to create a [`Sender`] and [`Receiver`]
5//! handle pair that form the channel.
6//!
7//! - The [`Sender`] handle is used by the producer to send the value.
8//! - The [`Receiver`] handle is used by the consumer to receive the value.
9//!
10//! Each handle can be used on other threads.
11//!
12//! - [`Sender::send`] will no block the calling thread.
13//! - [`Receiver::recv`] will **block** the calling thread.
14//!
15//! # Example
16//! ```rust
17//! # use std::time::Duration;
18//! let (tx, rx) = sync_oneshot::channel();
19//!
20//! std::thread::spawn(move || {
21//!     std::thread::sleep(Duration::from_millis(200));
22//!     tx.send(5).unwrap();
23//! });
24//!
25//! // blocking thread until a message available
26//! let val = rx.recv().unwrap();
27//! assert_eq!(val, 5);
28//! ```
29#[cfg(loom)]
30use loom::{
31    sync::{
32        atomic::{AtomicUsize, Ordering},
33        Arc,
34    },
35    thread,
36};
37
38use std::{fmt, time::Instant};
39#[cfg(not(loom))]
40use std::{
41    sync::{
42        atomic::{AtomicUsize, Ordering},
43        Arc,
44    },
45    thread,
46};
47
48use std::time::Duration;
49
50use crate::{notify::Notify, slot::Slot};
51
52mod error;
53mod notify;
54mod slot;
55
56pub use error::{RecvError, RecvTimeoutError, TryRecvError};
57
58/// Creates a new oneshot channel, returning the sender/receiver halves.
59///
60/// The [`Sender`] is used by the producer to send the value.
61/// The [`Receiver`] handle is used by the consumer to receive the value.
62///
63/// [`send`](Sender::send) will no block the calling thread. [`recv`](Receiver::recv)
64/// will **block** until a message is available.
65#[inline]
66pub fn channel<T>() -> (Sender<T>, Receiver<T>) {
67    let inner = Arc::new(Inner {
68        state: AtomicUsize::new(0),
69        value: Slot::new(),
70        notify: Notify::new(),
71    });
72
73    (
74        Sender {
75            inner: Some(inner.clone()),
76        },
77        Receiver { inner: Some(inner) },
78    )
79}
80
81/// Sends a value to the associated [`Receiver`].
82///
83/// This is created by the [`channel`] function.
84/// Messages can be sent using [`send`](Sender::send).
85#[derive(Debug)]
86pub struct Sender<T> {
87    inner: Option<Arc<Inner<T>>>,
88}
89
90/// Receive a value from the associated [`Sender`].
91///
92/// This is created by the [`channel`] function.
93/// Messages sent to the channel can be retrieved using [`recv`](Receiver::recv).
94/// [`recv`](Receiver::recv) method blocks thread.
95#[derive(Debug)]
96pub struct Receiver<T> {
97    inner: Option<Arc<Inner<T>>>,
98}
99
100unsafe impl<T> Send for Sender<T> where T: Send {}
101unsafe impl<T> Sync for Sender<T> where T: Send {}
102
103unsafe impl<T> Send for Receiver<T> where T: Send {}
104unsafe impl<T> Sync for Receiver<T> where T: Send {}
105
106struct Inner<T> {
107    state: AtomicUsize,
108    value: Slot<T>,
109    notify: Notify,
110}
111
112/*
113 *
114 * ===== impl Sender =====
115 *
116 */
117impl<T> Sender<T> {
118    /// Attempts to send a value on this channel, returning it back if it could not be sent.
119    ///
120    /// A successful send occurs when it is determined that the other end of the
121    /// channel has not hung up already. An unsuccessful send would be one where
122    /// the corresponding receiver has already been deallocated. Note that a
123    /// return value of [`Err`] means that the data will never be received, but
124    /// a return value of [`Ok`] does *not* mean that the data will be received.
125    /// It is possible for the corresponding receiver to hang up immediately
126    /// after this function returns [`Ok`].
127    ///
128    /// This method will never block the current thread.
129    /// # Example
130    /// ```rust
131    /// let (tx, rx) = sync_oneshot::channel();
132    /// std::thread::spawn(move || {
133    ///     if let Err(e) = tx.send(5) {
134    ///         println!("the receiver dropped");
135    ///     }
136    /// });
137    ///
138    /// match rx.recv() {
139    ///     Ok(v) => println!("got = {:?}", v),
140    ///     Err(_) => println!("the sender dropped"),
141    /// }
142    /// ```
143    #[inline]
144    pub fn send(mut self, value: T) -> Result<(), T> {
145        // take inner
146        // The case inner None is unreachable
147        let inner = self.inner.take().unwrap();
148
149        // set value
150        unsafe {
151            // SAFETY:
152            // Receiver don't access inner value until set status as VALUE_SENT
153            inner.value.set(value);
154        }
155
156        // set state as VALUE_SEND and notify
157        let prev_state = inner.set_complete();
158
159        if prev_state.is_closed() {
160            // SAFETY:
161            // Receiver already has been droped. So can access inner value.
162            return Err(unsafe { inner.consume_value().unwrap() });
163        }
164
165        if prev_state.is_waiting() {
166            unsafe {
167                inner.notify();
168            }
169        }
170
171        Ok(())
172    }
173
174    /// Returns true if the associated Receiver handle has been dropped.
175    ///
176    /// A Receiver is closed by either calling close explicitly or the Receiver value is dropped.
177    /// If true is returned, a call to send will always result in an error.
178    pub fn is_closed(&self) -> bool {
179        let inner = self.inner.as_ref().unwrap();
180        State(inner.state.load(Ordering::Acquire)).is_closed()
181    }
182}
183
184impl<T> Drop for Sender<T> {
185    fn drop(&mut self) {
186        if let Some(inner) = self.inner.take() {
187            let prev_state = inner.set_complete();
188
189            if prev_state.is_waiting() {
190                unsafe {
191                    inner.notify.notify();
192                }
193            }
194        }
195    }
196}
197
198/*
199 *
200 * ===== impl Receiver =====
201 *
202 */
203impl<T> Receiver<T> {
204    /// Attempts to wait for a value on this receiver, returning an error if
205    /// the corresponding channel has hung up.
206    ///
207    /// This function will always block the current thread if there is no data
208    /// available. Once a message is sent to the corresponding [`Sender`],
209    /// this receiver will wake up and return that message.
210    ///
211    /// If the corresponding [`Sender`] has disconnected, or it disconnects while
212    /// this call is blocking, this call will wake up and return [`Err`] to
213    /// indicate that no more messages can ever be received on this channel.
214    /// # Example
215    /// ```rust
216    /// let (tx, rx) = sync_oneshot::channel();
217    ///
218    /// let th_handle = std::thread::spawn(move || {
219    ///     tx.send(5).unwrap();
220    /// });
221    ///
222    /// th_handle.join().unwrap();
223    ///
224    /// assert_eq!(5, rx.recv().unwrap());
225    /// ```
226    #[inline]
227    pub fn recv(self) -> Result<T, RecvError> {
228        self.recv_inner(None).map_err(|_| RecvError)
229    }
230
231    /// Attempts to return a pending value on this receiver without blocking.
232    ///
233    /// This method will never block the caller in order to wait for data to
234    /// become available. Instead, this will always return immediately with a
235    /// possible option of pending data on the channel.
236    ///
237    /// This is useful for a flavor of “optimistic check” before deciding to
238    /// block on a receiver.
239    ///
240    /// Compared with recv, this function has two failure cases instead of one (one for disconnection, one for an empty buffer).
241    #[inline]
242    pub fn try_recv(&mut self) -> Result<T, TryRecvError> {
243        let result = if let Some(inner) = self.inner.as_ref() {
244            let state = State(inner.state.load(Ordering::Acquire));
245
246            if state.is_complete() {
247                unsafe {
248                    // SAFETY:
249                    // When state is complete, Sender no longer access value
250                    // Can access value safely
251                    match inner.consume_value() {
252                        Some(value) => Ok(value),
253                        None => Err(TryRecvError::Closed),
254                    }
255                }
256            } else if state.is_closed() {
257                Err(TryRecvError::Closed)
258            } else {
259                return Err(TryRecvError::Empty);
260            }
261        } else {
262            Err(TryRecvError::Closed)
263        };
264
265        self.inner = None;
266        result
267    }
268
269    /// Attempts to wait for a value on this receiver,
270    /// returning an error if the corresponding [`Sender`] half of
271    /// this channel has been dropped, or if deadline is reached.
272    #[cfg(not(loom))]
273    pub fn recv_deadline(&mut self, deadline: Instant) -> Result<T, RecvTimeoutError> {
274        let result = self.recv_inner(Some(deadline));
275
276        match result {
277            Ok(_) | Err(RecvTimeoutError::Closed) => {
278                self.inner = None;
279            }
280            _ => {}
281        }
282        result
283    }
284
285    /// Attempts to wait for a value on this receiver, returning an error if the
286    /// corresponding channel has hung up, or if it waits more than `timeout`.
287    ///
288    /// This function will always block the current thread if there is no data
289    /// available and it's possible for more data to be sent.
290    /// Once a message is sent to the corresponding [`Sender`]
291    /// this receiver will wake up and return that message.
292    ///
293    /// If the corresponding [`Sender`] has dropped, or it disconnects while
294    /// this call is blocking, this call will wake up and return [`Err`] to
295    /// indicate that no more messages can ever be received on this channel.
296    /// However, since channels are buffered, messages sent before the disconnect
297    /// will still be properly received.
298    #[cfg(not(loom))]
299    pub fn recv_timeout(&mut self, timeout: Duration) -> Result<T, RecvTimeoutError> {
300        match Instant::now().checked_add(timeout) {
301            Some(deadline) => self.recv_deadline(deadline),
302            // waits until Sender sent a value (same Receiver::recv)
303            // if return type of checked_add None, it will
304            // overflow and wait indefinitely
305            None => self.recv_inner(None),
306        }
307    }
308
309    fn recv_inner(&self, deadline: Option<Instant>) -> Result<T, RecvTimeoutError> {
310        if let Some(inner) = self.inner.as_ref() {
311            let mut state = inner.state.load(Ordering::Acquire);
312            loop {
313                if State(state).is_complete() {
314                    unsafe { break inner.consume_value().ok_or(RecvTimeoutError::Closed) }
315                }
316
317                if State(state).is_closed() {
318                    break Err(RecvTimeoutError::Closed);
319                }
320
321                if !State(state).is_waiting() {
322                    unsafe {
323                        inner.notify.set_current();
324                    }
325                }
326
327                if let Err(actual) = inner.state.compare_exchange_weak(
328                    state,
329                    state | WAITING,
330                    Ordering::Release,
331                    Ordering::Acquire,
332                ) {
333                    state = actual;
334                    continue;
335                }
336
337                match deadline {
338                    None => thread::park(),
339                    Some(d) => match d.checked_duration_since(Instant::now()) {
340                        Some(dur) => park_for(dur),
341                        None => {
342                            let prev = inner.state.fetch_and(!WAITING, Ordering::Acquire);
343                            if State(prev).is_complete() || State(prev).is_closed() {
344                                state = prev;
345                                continue;
346                            }
347                            break Err(RecvTimeoutError::Timeout);
348                        }
349                    },
350                }
351                state = inner.state.load(Ordering::Acquire);
352            }
353        } else {
354            Err(RecvTimeoutError::Closed)
355        }
356    }
357
358    /// Prevents the associated [`Sender`] handle from sending a value.
359    ///
360    /// Any `send` operation which happens after calling `close` is guaranteed
361    /// to fail. After calling `close`, [`try_recv`] should be called to
362    /// receive a value if one was sent **before** the call to `close`
363    /// completed.
364    ///
365    /// This function is useful to perform a graceful shutdown and ensure that a
366    /// value will not be sent into the channel and never received.
367    ///
368    /// `close` is no-op if a message is already received or the channel
369    /// is already closed.
370    ///
371    /// [`Sender`]: Sender
372    /// [`try_recv`]: Receiver::try_recv
373    ///
374    /// # Examples
375    ///
376    /// Prevent a value from being sent
377    ///
378    /// ```
379    /// use sync_oneshot::TryRecvError;
380    ///
381    /// # fn main() {
382    /// let (tx, mut rx) = sync_oneshot::channel();
383    ///
384    /// assert!(!tx.is_closed());
385    ///
386    /// rx.close();
387    ///
388    /// assert!(tx.is_closed());
389    /// assert!(tx.send("never received").is_err());
390    ///
391    /// match rx.try_recv() {
392    ///     Err(TryRecvError::Closed) => {}
393    ///     _ => unreachable!(),
394    /// }
395    /// # }
396    /// ```
397    ///
398    /// Receive a value sent **before** calling `close`
399    ///
400    /// ```
401    /// # fn main() {
402    /// let (tx, mut rx) = sync_oneshot::channel();
403    ///
404    /// assert!(tx.send("will receive").is_ok());
405    ///
406    /// rx.close();
407    ///
408    /// let msg = rx.try_recv().unwrap();
409    /// assert_eq!(msg, "will receive");
410    /// # }
411    /// ```
412    pub fn close(&mut self) {
413        if let Some(inner) = self.inner.as_ref() {
414            let _ = inner.set_close();
415        }
416    }
417}
418
419impl<T> Drop for Receiver<T> {
420    fn drop(&mut self) {
421        // if inner is some, Receiver::recv is not called before drop.
422        // Drop value or change state
423        if let Some(inner) = self.inner.take() {
424            let prev_state = inner.set_close();
425            if prev_state.is_complete() {
426                unsafe {
427                    inner.consume_value();
428                }
429            }
430        }
431    }
432}
433
434/*
435 *
436 * ===== impl Inner =====
437 *
438 */
439impl<T> Inner<T> {
440    #[inline]
441    fn set_complete(&self) -> State {
442        let mut state = self.state.load(Ordering::Relaxed);
443        loop {
444            if State(state).is_closed() {
445                break;
446            }
447
448            match self.state.compare_exchange_weak(
449                state,
450                state | VALUE_SENT,
451                Ordering::AcqRel,
452                Ordering::Relaxed,
453            ) {
454                Ok(_) => break,
455                Err(actual) => state = actual,
456            }
457        }
458        State(state)
459    }
460
461    #[inline]
462    fn set_close(&self) -> State {
463        State(self.state.fetch_or(CLOSED, Ordering::AcqRel))
464    }
465
466    #[inline]
467    unsafe fn notify(&self) {
468        unsafe {
469            self.notify.notify();
470        }
471    }
472
473    #[inline]
474    unsafe fn consume_value(&self) -> Option<T> {
475        unsafe { self.value.take() }
476    }
477}
478
479impl<T: fmt::Debug> fmt::Debug for Inner<T> {
480    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
481        f.debug_struct("Inner")
482            .field("state", &State(self.state.load(Ordering::Relaxed)))
483            .finish()
484    }
485}
486
487struct State(usize);
488
489const WAITING: usize = 0b0001;
490const VALUE_SENT: usize = 0b0010;
491const CLOSED: usize = 0b0100;
492
493/*
494 *
495 * ===== impl State =====
496 *
497 */
498impl State {
499    #[inline]
500    fn is_closed(&self) -> bool {
501        self.0 & CLOSED == CLOSED
502    }
503
504    #[inline]
505    fn is_waiting(&self) -> bool {
506        self.0 & WAITING == WAITING
507    }
508
509    #[inline]
510    fn is_complete(&self) -> bool {
511        self.0 & VALUE_SENT == VALUE_SENT
512    }
513}
514
515impl fmt::Debug for State {
516    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
517        f.debug_struct("State")
518            .field("is_complete", &self.is_complete())
519            .field("is_closed", &self.is_closed())
520            .field("is_waiting", &self.is_waiting())
521            .finish()
522    }
523}
524
525#[cfg(not(loom))]
526#[inline]
527fn park_for(dur: Duration) {
528    std::thread::park_timeout(dur);
529}
530
531// dummy function for passing compile on loom environment
532#[cfg(loom)]
533#[inline]
534fn park_for(_dur: Duration) {
535    unreachable!("timed park is not supported under loom");
536}