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