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}