Documentation
use crate::error::{TryRecvError, TrySendError};
use crossbeam_utils::Backoff;

#[inline(always)]
pub fn async_recv<T>(rx: &crossbeam_channel::Receiver<T>) -> Result<T, TryRecvError> {
    let backoff = Backoff::new();
    loop {
        match rx.try_recv() {
            Ok(value) => return Ok(value),
            Err(crossbeam_channel::TryRecvError::Empty) => {}
            Err(crossbeam_channel::TryRecvError::Disconnected) => {
                return Err(TryRecvError::Disconnected);
            }
        }

        if backoff.is_completed() {
            break;
        } else {
            backoff.snooze();
        }
    }

    Err(TryRecvError::Empty)
}

#[inline(always)]
pub fn async_send<T>(tx: &crossbeam_channel::Sender<T>, value: T) -> Result<(), TrySendError<T>> {
    let backoff = Backoff::new();
    let mut value = value;
    loop {
        match tx.try_send(value) {
            Ok(()) => return Ok(()),
            Err(crossbeam_channel::TrySendError::Full(v)) => {
                value = v;
            }
            Err(crossbeam_channel::TrySendError::Disconnected(v)) => {
                return Err(TrySendError::Disconnected(v));
            }
        }

        if backoff.is_completed() {
            break;
        } else {
            backoff.snooze();
        }
    }

    Err(TrySendError::Full(value))
}