Skip to main content

std/sync/
oneshot.rs

1//! A single-producer, single-consumer (oneshot) channel.
2//!
3//! This is an experimental module, so the API will likely change.
4
5use crate::sync::mpmc;
6use crate::sync::mpsc::{RecvError, SendError};
7use crate::time::{Duration, Instant};
8use crate::{error, fmt};
9
10/// Creates a new oneshot channel, returning the sender/receiver halves.
11///
12/// # Examples
13///
14/// ```
15/// #![feature(oneshot_channel)]
16/// use std::sync::oneshot;
17/// use std::thread;
18///
19/// let (sender, receiver) = oneshot::channel();
20///
21/// // Spawn off an expensive computation.
22/// thread::spawn(move || {
23/// #   fn expensive_computation() -> i32 { 42 }
24///     sender.send(expensive_computation()).unwrap();
25///     // `sender` is consumed by `send`, so we cannot use it anymore.
26/// });
27///
28/// # fn do_other_work() -> i32 { 42 }
29/// do_other_work();
30///
31/// // Let's see what that answer was...
32/// println!("{:?}", receiver.recv().unwrap());
33/// // `receiver` is consumed by `recv`, so we cannot use it anymore.
34/// ```
35#[must_use]
36#[unstable(feature = "oneshot_channel", issue = "143674")]
37pub fn channel<T>() -> (Sender<T>, Receiver<T>) {
38    // Using a `sync_channel` with capacity 1 means that the internal implementation will use the
39    // `Array`-flavored channel implementation.
40    let (sender, receiver) = mpmc::sync_channel(1);
41    (Sender { inner: sender }, Receiver { inner: receiver })
42}
43
44////////////////////////////////////////////////////////////////////////////////////////////////////
45// Sender
46////////////////////////////////////////////////////////////////////////////////////////////////////
47
48/// The sending half of a oneshot channel.
49///
50/// # Examples
51///
52/// ```
53/// #![feature(oneshot_channel)]
54/// use std::sync::oneshot;
55/// use std::thread;
56///
57/// let (sender, receiver) = oneshot::channel();
58///
59/// thread::spawn(move || {
60///     sender.send("Hello from thread!").unwrap();
61/// });
62///
63/// assert_eq!(receiver.recv().unwrap(), "Hello from thread!");
64/// ```
65///
66/// `Sender` cannot be sent between threads if it is sending non-`Send` types.
67///
68/// ```compile_fail
69/// #![feature(oneshot_channel)]
70/// use std::sync::oneshot;
71/// use std::thread;
72/// use std::ptr;
73///
74/// let (sender, receiver) = oneshot::channel();
75///
76/// struct NotSend(*mut ());
77/// thread::spawn(move || {
78///     sender.send(NotSend(ptr::null_mut()));
79/// });
80///
81/// let reply = receiver.try_recv().unwrap();
82/// ```
83#[unstable(feature = "oneshot_channel", issue = "143674")]
84pub struct Sender<T> {
85    /// The `oneshot` channel is simply a wrapper around a `mpmc` channel.
86    inner: mpmc::Sender<T>,
87}
88
89// SAFETY: Sending a value requires ownership of the sender. Shared references only inspect
90// channel state, so they cannot send a value of a non-`Send` type from another thread.
91#[unstable(feature = "oneshot_channel", issue = "143674")]
92unsafe impl<T> Sync for Sender<T> {}
93
94impl<T> Sender<T> {
95    /// Attempts to send a value through this channel. This can only fail if the corresponding
96    /// [`Receiver<T>`] has been dropped.
97    ///
98    /// This method is non-blocking (wait-free).
99    ///
100    /// # Examples
101    ///
102    /// ```
103    /// #![feature(oneshot_channel)]
104    /// use std::sync::oneshot;
105    /// use std::thread;
106    ///
107    /// let (tx, rx) = oneshot::channel();
108    ///
109    /// thread::spawn(move || {
110    ///     // Perform some computation.
111    ///     let result = 2 + 2;
112    ///     tx.send(result).unwrap();
113    /// });
114    ///
115    /// assert_eq!(rx.recv().unwrap(), 4);
116    /// ```
117    #[unstable(feature = "oneshot_channel", issue = "143674")]
118    pub fn send(self, t: T) -> Result<(), SendError<T>> {
119        self.inner.send(t)
120    }
121
122    /// Returns `true` if the corresponding [`Receiver`] has been dropped.
123    ///
124    /// If this method returns `true`, [`send`](Self::send) is guaranteed to return an error.
125    ///
126    /// On the receiving side, [`Receiver::is_ready`] checks whether a value is available without
127    /// consuming the receiver.
128    ///
129    /// A return value of `false` does not guarantee that a later call to [`send`](Self::send) will
130    /// succeed. The receiver may be dropped immediately after this method returns.
131    #[unstable(feature = "oneshot_channel", issue = "143674")]
132    pub fn is_closed(&self) -> bool {
133        self.inner.is_disconnected()
134    }
135}
136
137#[unstable(feature = "oneshot_channel", issue = "143674")]
138impl<T> fmt::Debug for Sender<T> {
139    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
140        f.debug_struct("Sender").finish_non_exhaustive()
141    }
142}
143
144////////////////////////////////////////////////////////////////////////////////////////////////////
145// Receiver
146////////////////////////////////////////////////////////////////////////////////////////////////////
147
148/// The receiving half of a oneshot channel.
149///
150/// # Examples
151///
152/// ```
153/// #![feature(oneshot_channel)]
154/// use std::sync::oneshot;
155/// use std::thread;
156/// use std::time::Duration;
157///
158/// let (sender, receiver) = oneshot::channel();
159///
160/// thread::spawn(move || {
161///     thread::sleep(Duration::from_millis(100));
162///     sender.send("Hello after delay!").unwrap();
163/// });
164///
165/// println!("Waiting for message...");
166/// println!("{}", receiver.recv().unwrap());
167/// ```
168///
169/// `Receiver` cannot be sent between threads if it is receiving non-`Send` types.
170///
171/// ```compile_fail
172/// # #![feature(oneshot_channel)]
173/// # use std::sync::oneshot;
174/// # use std::thread;
175/// # use std::ptr;
176/// #
177/// let (sender, receiver) = oneshot::channel();
178///
179/// struct NotSend(*mut ());
180/// sender.send(NotSend(ptr::null_mut()));
181///
182/// thread::spawn(move || {
183///     let reply = receiver.try_recv().unwrap();
184/// });
185/// ```
186#[unstable(feature = "oneshot_channel", issue = "143674")]
187pub struct Receiver<T> {
188    /// The `oneshot` channel is simply a wrapper around a `mpmc` channel.
189    inner: mpmc::Receiver<T>,
190}
191
192// SAFETY: Receiving a value requires ownership of the receiver. Shared references only inspect
193// channel state, so they cannot access a value of a non-`Send` type from another thread.
194#[unstable(feature = "oneshot_channel", issue = "143674")]
195unsafe impl<T> Sync for Receiver<T> {}
196
197impl<T> Receiver<T> {
198    /// Receives the value from the sending end, blocking the calling thread until it gets it.
199    ///
200    /// Can only fail if the corresponding [`Sender<T>`] has been dropped.
201    ///
202    /// # Examples
203    ///
204    /// ```
205    /// #![feature(oneshot_channel)]
206    /// use std::sync::oneshot;
207    /// use std::thread;
208    /// use std::time::Duration;
209    ///
210    /// let (tx, rx) = oneshot::channel();
211    ///
212    /// thread::spawn(move || {
213    ///     thread::sleep(Duration::from_millis(500));
214    ///     tx.send("Done!").unwrap();
215    /// });
216    ///
217    /// // This will block until the message arrives.
218    /// println!("{}", rx.recv().unwrap());
219    /// ```
220    #[unstable(feature = "oneshot_channel", issue = "143674")]
221    pub fn recv(self) -> Result<T, RecvError> {
222        self.inner.recv()
223    }
224
225    // Fallible methods.
226
227    /// Returns `Ok(true)` if the sender has sent a value over the channel.
228    ///
229    /// Returns `Ok(false)` if no value has been sent, but the corresponding [`Sender<T>`] still
230    /// exists (has not been dropped yet).
231    ///
232    /// Returns a [`RecvError`] if the corresponding [`Sender<T>`] has been dropped before a value
233    /// has been sent.
234    ///
235    /// If this method returns `Ok(true)`, then any of the `recv` methods are guaranteed to return
236    /// the value successfully without blocking.
237    ///
238    /// # Warnings
239    ///
240    /// A return value of `Ok(false)` does not guarantee that a later receive operation will block.
241    /// The sender may send a value or be dropped immediately after this method returns.
242    ///
243    /// Polling this method in a loop just to wait for a value wastes CPU time. Use
244    /// [`recv`](Self::recv) or [`recv_timeout`](Self::recv_timeout) instead.
245    #[unstable(feature = "oneshot_channel", issue = "143674")]
246    pub fn is_ready(&self) -> Result<bool, RecvError> {
247        // Sending consumes and drops the sender after writing the value, so the channel is ready
248        // only when it is both disconnected and nonempty.
249        if !self.inner.is_disconnected() {
250            return Ok(false);
251        }
252
253        if self.inner.is_empty() { Err(RecvError) } else { Ok(true) }
254    }
255
256    /// Attempts to return a pending value on this receiver without blocking.
257    ///
258    /// To check whether a value is available without consuming the receiver, use
259    /// [`is_ready`](Self::is_ready).
260    ///
261    /// # Examples
262    ///
263    /// ```
264    /// #![feature(oneshot_channel)]
265    /// use std::sync::oneshot;
266    /// use std::thread;
267    /// use std::time::Duration;
268    ///
269    /// let (sender, mut receiver) = oneshot::channel();
270    ///
271    /// thread::spawn(move || {
272    ///     thread::sleep(Duration::from_millis(100));
273    ///     sender.send(42).unwrap();
274    /// });
275    ///
276    /// // Keep trying until we get the message, doing other work in the process.
277    /// loop {
278    ///     match receiver.try_recv() {
279    ///         Ok(value) => {
280    ///             assert_eq!(value, 42);
281    ///             break;
282    ///         }
283    ///         Err(oneshot::TryRecvError::Empty(rx)) => {
284    ///             // Retake ownership of the receiver.
285    ///             receiver = rx;
286    /// #           fn do_other_work() { thread::sleep(Duration::from_millis(25)); }
287    ///             do_other_work();
288    ///         }
289    ///         Err(oneshot::TryRecvError::Disconnected) => panic!("Sender disconnected"),
290    ///     }
291    /// }
292    /// ```
293    #[unstable(feature = "oneshot_channel", issue = "143674")]
294    pub fn try_recv(self) -> Result<T, TryRecvError<T>> {
295        self.inner.try_recv().map_err(|err| match err {
296            mpmc::TryRecvError::Empty => TryRecvError::Empty(self),
297            mpmc::TryRecvError::Disconnected => TryRecvError::Disconnected,
298        })
299    }
300
301    /// Attempts to wait for a value on this receiver, returning an error if the corresponding
302    /// [`Sender`] half of this channel has been dropped, or if it waits more than `timeout`.
303    ///
304    /// # Examples
305    ///
306    /// ```
307    /// #![feature(oneshot_channel)]
308    /// use std::sync::oneshot;
309    /// use std::thread;
310    /// use std::time::Duration;
311    ///
312    /// let (sender, receiver) = oneshot::channel();
313    ///
314    /// thread::spawn(move || {
315    ///     thread::sleep(Duration::from_millis(500));
316    ///     sender.send("Success!").unwrap();
317    /// });
318    ///
319    /// // Wait up to 1 second for the message
320    /// match receiver.recv_timeout(Duration::from_secs(1)) {
321    ///     Ok(msg) => println!("Received: {}", msg),
322    ///     Err(oneshot::RecvTimeoutError::Timeout(_)) => println!("Timed out!"),
323    ///     Err(oneshot::RecvTimeoutError::Disconnected) => println!("Sender dropped!"),
324    /// }
325    /// ```
326    #[unstable(feature = "oneshot_channel", issue = "143674")]
327    pub fn recv_timeout(self, timeout: Duration) -> Result<T, RecvTimeoutError<T>> {
328        self.inner.recv_timeout(timeout).map_err(|err| match err {
329            mpmc::RecvTimeoutError::Timeout => RecvTimeoutError::Timeout(self),
330            mpmc::RecvTimeoutError::Disconnected => RecvTimeoutError::Disconnected,
331        })
332    }
333
334    /// Attempts to wait for a value on this receiver, returning an error if the corresponding
335    /// [`Sender`] half of this channel has been dropped, or if `deadline` is reached.
336    ///
337    /// # Examples
338    ///
339    /// ```
340    /// #![feature(oneshot_channel)]
341    /// use std::sync::oneshot;
342    /// use std::thread;
343    /// use std::time::{Duration, Instant};
344    ///
345    /// let (sender, receiver) = oneshot::channel();
346    ///
347    /// thread::spawn(move || {
348    ///     thread::sleep(Duration::from_millis(100));
349    ///     sender.send("Just in time!").unwrap();
350    /// });
351    ///
352    /// let deadline = Instant::now() + Duration::from_millis(500);
353    /// match receiver.recv_deadline(deadline) {
354    ///     Ok(msg) => println!("Received: {}", msg),
355    ///     Err(oneshot::RecvTimeoutError::Timeout(_)) => println!("Missed deadline!"),
356    ///     Err(oneshot::RecvTimeoutError::Disconnected) => println!("Sender dropped!"),
357    /// }
358    /// ```
359    #[unstable(feature = "oneshot_channel", issue = "143674")]
360    pub fn recv_deadline(self, deadline: Instant) -> Result<T, RecvTimeoutError<T>> {
361        self.inner.recv_deadline(deadline).map_err(|err| match err {
362            mpmc::RecvTimeoutError::Timeout => RecvTimeoutError::Timeout(self),
363            mpmc::RecvTimeoutError::Disconnected => RecvTimeoutError::Disconnected,
364        })
365    }
366}
367
368#[unstable(feature = "oneshot_channel", issue = "143674")]
369impl<T> fmt::Debug for Receiver<T> {
370    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
371        f.debug_struct("Receiver").finish_non_exhaustive()
372    }
373}
374
375////////////////////////////////////////////////////////////////////////////////////////////////////
376// Receiver Errors
377////////////////////////////////////////////////////////////////////////////////////////////////////
378
379/// An error returned from the [`try_recv`](Receiver::try_recv) method.
380///
381/// See the documentation for [`try_recv`] for more information on how to use this error.
382///
383/// [`try_recv`]: Receiver::try_recv
384#[unstable(feature = "oneshot_channel", issue = "143674")]
385pub enum TryRecvError<T> {
386    /// The [`Sender`] has not sent a message yet, but it might in the future (as it has not yet
387    /// disconnected). This variant contains the [`Receiver`] that [`try_recv`](Receiver::try_recv)
388    /// took ownership over.
389    Empty(Receiver<T>),
390    /// The corresponding [`Sender`] half of this channel has become disconnected, and there will
391    /// never be any more data sent over the channel.
392    Disconnected,
393}
394
395/// An error returned from the [`recv_timeout`](Receiver::recv_timeout) or
396/// [`recv_deadline`](Receiver::recv_deadline) methods.
397///
398/// # Examples
399///
400/// Usage of this error is similar to [`TryRecvError`].
401///
402/// ```
403/// #![feature(oneshot_channel)]
404/// use std::sync::oneshot::{self, RecvTimeoutError};
405/// use std::thread;
406/// use std::time::Duration;
407///
408/// let (sender, receiver) = oneshot::channel();
409///
410/// let send_failure = thread::spawn(move || {
411///     // Simulate a long computation that takes longer than our timeout.
412///     thread::sleep(Duration::from_millis(250));
413///
414///     // This will likely fail to send because we drop the receiver in the main thread.
415///     sender.send("Goodbye!".to_string()).unwrap();
416/// });
417///
418/// // Try to receive the message with a short timeout.
419/// match receiver.recv_timeout(Duration::from_millis(10)) {
420///     Ok(msg) => println!("Received: {}", msg),
421///     Err(RecvTimeoutError::Timeout(rx)) => {
422///         println!("Timed out waiting for message!");
423///
424///         // Note that you can reuse the receiver without dropping it.
425///         drop(rx);
426///     },
427///     Err(RecvTimeoutError::Disconnected) => println!("Sender dropped!"),
428/// }
429///
430/// send_failure.join().unwrap_err();
431/// ```
432#[unstable(feature = "oneshot_channel", issue = "143674")]
433pub enum RecvTimeoutError<T> {
434    /// The [`Sender`] has not sent a message yet, but it might in the future (as it has not yet
435    /// disconnected). This variant contains the [`Receiver`] that either
436    /// [`recv_timeout`](Receiver::recv_timeout) or [`recv_deadline`](Receiver::recv_deadline) took
437    /// ownership over.
438    Timeout(Receiver<T>),
439    /// The corresponding [`Sender`] half of this channel has become disconnected, and there will
440    /// never be any more data sent over the channel.
441    Disconnected,
442}
443
444#[unstable(feature = "oneshot_channel", issue = "143674")]
445impl<T> fmt::Debug for TryRecvError<T> {
446    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
447        f.debug_tuple("TryRecvError").finish_non_exhaustive()
448    }
449}
450
451#[unstable(feature = "oneshot_channel", issue = "143674")]
452impl<T> fmt::Display for TryRecvError<T> {
453    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
454        match *self {
455            TryRecvError::Empty(..) => "receiving on an empty oneshot channel".fmt(f),
456            TryRecvError::Disconnected => "receiving on a closed oneshot channel".fmt(f),
457        }
458    }
459}
460
461#[unstable(feature = "oneshot_channel", issue = "143674")]
462impl<T> error::Error for TryRecvError<T> {}
463
464#[unstable(feature = "oneshot_channel", issue = "143674")]
465impl<T> From<RecvError> for TryRecvError<T> {
466    /// Converts a `RecvError` into a `TryRecvError`.
467    ///
468    /// This conversion always returns `TryRecvError::Disconnected`.
469    ///
470    /// No data is allocated on the heap.
471    fn from(err: RecvError) -> TryRecvError<T> {
472        match err {
473            RecvError => TryRecvError::Disconnected,
474        }
475    }
476}
477
478#[unstable(feature = "oneshot_channel", issue = "143674")]
479impl<T> fmt::Debug for RecvTimeoutError<T> {
480    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
481        f.debug_tuple("RecvTimeoutError").finish_non_exhaustive()
482    }
483}
484
485#[unstable(feature = "oneshot_channel", issue = "143674")]
486impl<T> fmt::Display for RecvTimeoutError<T> {
487    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
488        match *self {
489            RecvTimeoutError::Timeout(..) => "timed out waiting on oneshot channel".fmt(f),
490            RecvTimeoutError::Disconnected => "receiving on a closed oneshot channel".fmt(f),
491        }
492    }
493}
494
495#[unstable(feature = "oneshot_channel", issue = "143674")]
496impl<T> error::Error for RecvTimeoutError<T> {}
497
498#[unstable(feature = "oneshot_channel", issue = "143674")]
499impl<T> From<RecvError> for RecvTimeoutError<T> {
500    /// Converts a `RecvError` into a `RecvTimeoutError`.
501    ///
502    /// This conversion always returns `RecvTimeoutError::Disconnected`.
503    ///
504    /// No data is allocated on the heap.
505    fn from(err: RecvError) -> RecvTimeoutError<T> {
506        match err {
507            RecvError => RecvTimeoutError::Disconnected,
508        }
509    }
510}