#[cfg(not(all(loom, test)))]
pub(crate) use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
#[cfg(not(all(loom, test)))]
pub(crate) use std::sync::{Arc, Mutex, mpsc};
#[cfg(not(all(loom, test)))]
pub(crate) use std::thread;
#[cfg(all(loom, test))]
pub(crate) use loom::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
#[cfg(all(loom, test))]
pub(crate) use loom::sync::{Arc, Mutex};
#[cfg(all(loom, test))]
pub(crate) use loom::thread;
#[cfg(all(loom, test))]
pub(crate) mod mpsc {
use std::collections::VecDeque;
use std::time::Duration;
pub(crate) use std::sync::mpsc::{
RecvError, RecvTimeoutError, SendError, TryRecvError, TrySendError,
};
use loom::sync::{Arc, Condvar, Mutex, MutexGuard};
struct State<T> {
queue: VecDeque<T>,
bound: Option<usize>,
sender: bool,
receiver: bool,
}
struct Shared<T> {
state: Mutex<State<T>>,
ready: Condvar,
}
impl<T> Shared<T> {
fn state(&self) -> MutexGuard<'_, State<T>> {
self.state.lock().unwrap_or_else(|e| e.into_inner())
}
}
fn with_bound<T>(bound: Option<usize>) -> Arc<Shared<T>> {
Arc::new(Shared {
state: Mutex::new(State {
queue: VecDeque::new(),
bound,
sender: true,
receiver: true,
}),
ready: Condvar::new(),
})
}
pub(crate) fn channel<T>() -> (Sender<T>, Receiver<T>) {
let shared = with_bound(None);
(Sender(shared.clone()), Receiver(shared))
}
pub(crate) fn sync_channel<T>(bound: usize) -> (SyncSender<T>, Receiver<T>) {
let shared = with_bound(Some(bound));
(SyncSender(shared.clone()), Receiver(shared))
}
pub(crate) struct Sender<T>(Arc<Shared<T>>);
pub(crate) struct SyncSender<T>(Arc<Shared<T>>);
pub(crate) struct Receiver<T>(Arc<Shared<T>>);
fn push<T>(shared: &Shared<T>, message: T) -> Result<(), TrySendError<T>> {
let mut state = shared.state();
if !state.receiver {
return Err(TrySendError::Disconnected(message));
}
if state.bound.is_some_and(|bound| state.queue.len() >= bound) {
return Err(TrySendError::Full(message));
}
state.queue.push_back(message);
drop(state);
shared.ready.notify_one();
Ok(())
}
impl<T> Sender<T> {
pub(crate) fn send(&self, message: T) -> Result<(), SendError<T>> {
push(&self.0, message).map_err(|e| match e {
TrySendError::Full(message) | TrySendError::Disconnected(message) => {
SendError(message)
}
})
}
}
impl<T> SyncSender<T> {
pub(crate) fn try_send(&self, message: T) -> Result<(), TrySendError<T>> {
push(&self.0, message)
}
}
fn hang_up<T>(shared: &Shared<T>) {
shared.state().sender = false;
shared.ready.notify_all();
}
impl<T> Drop for Sender<T> {
fn drop(&mut self) {
hang_up(&self.0);
}
}
impl<T> Drop for SyncSender<T> {
fn drop(&mut self) {
hang_up(&self.0);
}
}
impl<T> Drop for Receiver<T> {
fn drop(&mut self) {
self.0.state().receiver = false;
}
}
impl<T> Receiver<T> {
pub(crate) fn recv(&self) -> Result<T, RecvError> {
let mut state = self.0.state();
loop {
if let Some(message) = state.queue.pop_front() {
return Ok(message);
}
if !state.sender {
return Err(RecvError);
}
state = self.0.ready.wait(state).unwrap_or_else(|e| e.into_inner());
}
}
pub(crate) fn recv_timeout(&self, _: Duration) -> Result<T, RecvTimeoutError> {
self.recv()
.map_err(|RecvError| RecvTimeoutError::Disconnected)
}
pub(crate) fn try_recv(&self) -> Result<T, TryRecvError> {
let mut state = self.0.state();
match state.queue.pop_front() {
Some(message) => Ok(message),
None if state.sender => Err(TryRecvError::Empty),
None => Err(TryRecvError::Disconnected),
}
}
}
}