use core::{
cell::SyncUnsafeCell,
future::{self, IntoFuture},
marker::PhantomPinned,
pin::Pin,
};
pub trait TrCancellationToken: Clone {
fn is_cancelled(&self) -> bool;
fn can_be_cancelled(&self) -> bool;
fn cancellation(self: Pin<&mut Self>) -> impl IntoFuture<Output = ()>;
}
pub trait TrMayCancel<'a>
where
Self: 'a + Sized + IntoFuture
{
type MayCancelOutput;
fn may_cancel_with<'f, C: TrCancellationToken>(
self,
cancel: Pin<&'f mut C>,
) -> impl IntoFuture<Output = Self::MayCancelOutput>
where
Self: 'f;
}
#[derive(Debug, Default, Clone, Copy)]
pub struct CancelledToken(PhantomPinned);
impl CancelledToken {
pub const fn new() -> Self {
CancelledToken(PhantomPinned)
}
pub fn pinned() -> Pin<&'static mut Self> {
static mut SHARED: SyncUnsafeCell<CancelledToken> =
SyncUnsafeCell::new(CancelledToken::new());
unsafe {
#[allow(static_mut_refs)]
Pin::new_unchecked(SHARED.get_mut())
}
}
pub const fn is_cancelled(&self) -> bool {
true
}
pub const fn can_be_cancelled(&self) -> bool {
false
}
pub fn cancellation(self: Pin<&mut Self>) -> future::Ready<()> {
future::ready(())
}
}
impl TrCancellationToken for CancelledToken {
#[inline]
fn is_cancelled(&self) -> bool {
CancelledToken::is_cancelled(self)
}
#[inline]
fn can_be_cancelled(&self) -> bool {
CancelledToken::can_be_cancelled(self)
}
#[inline]
fn cancellation(self: Pin<&mut Self>) -> impl IntoFuture<Output = ()> {
CancelledToken::cancellation(self)
}
}
#[derive(Debug, Default, Clone, Copy)]
pub struct NonCancellableToken(PhantomPinned);
impl NonCancellableToken {
pub const fn new() -> Self {
NonCancellableToken(PhantomPinned)
}
pub fn pinned() -> Pin<&'static mut Self> {
static mut SHARED: SyncUnsafeCell<NonCancellableToken> =
SyncUnsafeCell::new(NonCancellableToken::new());
unsafe {
#[allow(static_mut_refs)]
Pin::new_unchecked(SHARED.get_mut())
}
}
pub const fn is_cancelled(&self) -> bool {
false
}
pub const fn can_be_cancelled(&self) -> bool {
false
}
pub fn cancellation(self: Pin<&mut Self>) -> future::Pending<()> {
future::pending()
}
}
impl TrCancellationToken for NonCancellableToken {
#[inline]
fn is_cancelled(&self) -> bool {
NonCancellableToken::is_cancelled(self)
}
#[inline]
fn can_be_cancelled(&self) -> bool {
NonCancellableToken::can_be_cancelled(self)
}
#[inline]
fn cancellation(self: Pin<&mut Self>) -> impl IntoFuture<Output = ()> {
NonCancellableToken::cancellation(self)
}
}