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