#![cfg_attr(feature = "no_std", no_std)]
extern crate alloc;
mod cons;
mod internal;
macro_rules! impl_async_cell_part1 {
($cell_use:expr, $inner:ty, $inner_arg:ident, $shared:ident) => {
use core::{fmt, future::Future, ops::Deref, pin::Pin, task::Context, task::Poll};
#[doc = $cell_use]
#[repr(transparent)]
#[must_use]
#[derive(Clone, Copy)]
pub struct Take<C>(pub C);
#[repr(transparent)]
#[must_use]
pub struct TakeWeak<T>(pub Weak<AsyncCell<T>>);
impl<T> Clone for TakeWeak<T> {
fn clone(&self) -> Self {
Self(self.0.clone())
}
}
#[repr(transparent)]
#[must_use]
#[cfg(feature = "weakref")]
pub struct TakeRef<T>(pub weakref::Ref<AsyncCell<T>>);
#[cfg(feature = "weakref")]
impl<T> Clone for TakeRef<T> {
fn clone(&self) -> Self {
*self
}
}
#[cfg(feature = "weakref")]
impl<T> Copy for TakeRef<T> {}
#[doc = $cell_use]
#[repr(transparent)]
#[must_use]
#[derive(Clone, Copy)]
pub struct Get<C>(pub C);
#[repr(transparent)]
#[must_use]
pub struct GetWeak<T>(pub Weak<AsyncCell<T>>);
impl<T> Clone for GetWeak<T> {
fn clone(&self) -> Self {
Self(self.0.clone())
}
}
#[repr(transparent)]
#[must_use]
#[cfg(feature = "weakref")]
pub struct GetRef<T>(pub weakref::Ref<AsyncCell<T>>);
#[cfg(feature = "weakref")]
impl<T> Clone for GetRef<T> {
fn clone(&self) -> Self {
*self
}
}
#[cfg(feature = "weakref")]
impl<T> Copy for GetRef<T> {}
pub struct GuardedCell<T, C: Deref<Target = AsyncCell<T>>> {
inner: C,
cancel: Option<T>,
}
pub struct AsyncCell<$inner_arg = ()> {
cell: $inner,
}
};
}
macro_rules! impl_async_cell_part2 {
($cell_use:expr, $shared:ident) => {
impl<T> AsyncCell<T> {
#[doc = $cell_use]
pub fn set(&self, value: T) {
crate::internal::set(&self.cell, value);
}
#[doc = $cell_use]
pub fn take(&self) -> Take<&Self> {
Take(self)
}
#[doc = $cell_use]
pub fn get(&self) -> Get<&Self>
where
T: Clone,
{
Get(self)
}
#[doc = $cell_use]
pub fn try_take(&self) -> Option<T> {
crate::internal::try_take(&self.cell)
}
#[doc = $cell_use]
pub fn try_get(&self) -> Option<T>
where
T: Clone,
{
crate::internal::try_get(&self.cell)
}
pub fn or_set(&self, value: T) {
crate::internal::or_set(&self.cell, value);
}
pub fn is_set(&self) -> bool {
crate::internal::is_set(&self.cell)
}
pub fn replace(&self, value: T) -> Option<T> {
crate::internal::set(&self.cell, value)
}
pub fn update(&self, with: impl FnOnce(Option<T>) -> Option<T>) {
crate::internal::update(&self.cell, with);
}
pub fn update_some(&self, with: impl FnOnce(T) -> T) {
crate::internal::update(&self.cell, |x| match x {
Some(x) => Some(with(x)),
None => None,
});
}
pub fn into_inner(self) -> Option<T> {
crate::internal::into_inner(self.cell)
}
#[doc = $cell_use]
pub fn guard(&self, cancel: T) -> GuardedCell<T, &Self> {
GuardedCell {
inner: self,
cancel: Some(cancel),
}
}
}
impl AsyncCell<()> {
pub fn notify(&self) {
crate::internal::set(&self.cell, ());
}
pub fn wait(&self) -> Take<&AsyncCell> {
Take(&self)
}
pub fn wait_shared(self: &$shared<Self>) -> Take<$shared<AsyncCell>> {
Take(self.clone())
}
}
impl<T> AsyncCell<T> {
pub fn shared() -> $shared<Self> {
AsyncCell::new().into_shared()
}
pub fn into_shared(self) -> $shared<Self> {
$shared::new(self)
}
pub fn take_shared(self: &$shared<Self>) -> Take<$shared<Self>> {
Take(self.clone())
}
pub fn get_shared(self: &$shared<Self>) -> Get<$shared<Self>>
where
T: Clone,
{
Get(self.clone())
}
pub fn guard_shared(self: &$shared<Self>, cancel: T) -> GuardedCell<T, $shared<Self>> {
GuardedCell {
inner: self.clone(),
cancel: Some(cancel),
}
}
#[doc = $cell_use]
pub fn take_weak(self: &$shared<Self>) -> TakeWeak<T> {
TakeWeak($shared::downgrade(self))
}
#[doc = $cell_use]
pub fn get_weak(self: &$shared<Self>) -> GetWeak<T>
where
T: Clone,
{
GetWeak($shared::downgrade(self))
}
}
impl<T> Default for AsyncCell<T> {
fn default() -> Self {
AsyncCell::new()
}
}
impl<T: fmt::Debug + Clone> fmt::Debug for AsyncCell<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
crate::internal::debug_state(&self.cell, f)
}
}
impl<T, C> Future for Take<C>
where
C: Deref<Target = AsyncCell<T>>,
{
type Output = T;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<T> {
crate::internal::poll_take(&self.0.cell, cx.waker())
}
}
impl<T, C> Future for &Take<C>
where
C: Deref<Target = AsyncCell<T>>,
{
type Output = T;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<T> {
crate::internal::poll_take(&self.0.cell, cx.waker())
}
}
impl<T> TakeWeak<T> {
pub fn upgrade(&self) -> Option<Take<$shared<AsyncCell<T>>>> {
Some(Take(self.0.upgrade()?))
}
}
impl<T> Future for TakeWeak<T> {
type Output = Option<T>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<T>> {
if let Some(cell) = self.0.upgrade() {
crate::internal::poll_take(&cell.cell, cx.waker()).map(Some)
} else {
Poll::Ready(None)
}
}
}
impl<T> Future for &TakeWeak<T> {
type Output = Option<T>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<T>> {
if let Some(cell) = self.0.upgrade() {
crate::internal::poll_take(&cell.cell, cx.waker()).map(Some)
} else {
Poll::Ready(None)
}
}
}
#[cfg(feature = "weakref")]
impl<T> Future for TakeRef<T> {
type Output = Option<T>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<T>> {
let guard = &weakref::pin();
if let Some(cell) = self.0.get(&guard) {
crate::internal::poll_take(&cell.cell, cx.waker()).map(Some)
} else {
Poll::Ready(None)
}
}
}
#[cfg(feature = "weakref")]
impl<T> Future for &TakeRef<T> {
type Output = Option<T>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<T>> {
let guard = &weakref::pin();
if let Some(cell) = self.0.get(&guard) {
crate::internal::poll_take(&cell.cell, cx.waker()).map(Some)
} else {
Poll::Ready(None)
}
}
}
impl<T, C> Future for Get<C>
where
C: Deref<Target = AsyncCell<T>>,
T: Clone,
{
type Output = T;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<T> {
crate::internal::poll_get(&self.0.cell, cx.waker())
}
}
impl<T, C> Future for &Get<C>
where
C: Deref<Target = AsyncCell<T>>,
T: Clone,
{
type Output = T;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<T> {
crate::internal::poll_get(&self.0.cell, cx.waker())
}
}
impl<T> GetWeak<T> {
pub fn upgrade(&self) -> Option<Get<$shared<AsyncCell<T>>>> {
Some(Get(self.0.upgrade()?))
}
}
impl<T: Clone> Future for GetWeak<T> {
type Output = Option<T>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<T>> {
if let Some(cell) = self.0.upgrade() {
crate::internal::poll_get(&cell.cell, cx.waker()).map(Some)
} else {
Poll::Ready(None)
}
}
}
impl<T: Clone> Future for &GetWeak<T> {
type Output = Option<T>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<T>> {
if let Some(cell) = self.0.upgrade() {
crate::internal::poll_get(&cell.cell, cx.waker()).map(Some)
} else {
Poll::Ready(None)
}
}
}
#[cfg(feature = "weakref")]
impl<T: Clone> Future for GetRef<T> {
type Output = Option<T>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<T>> {
let guard = &weakref::pin();
if let Some(cell) = self.0.get(&guard) {
crate::internal::poll_get(&cell.cell, cx.waker()).map(Some)
} else {
Poll::Ready(None)
}
}
}
#[cfg(feature = "weakref")]
impl<T: Clone> Future for &GetRef<T> {
type Output = Option<T>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<T>> {
let guard = &weakref::pin();
if let Some(cell) = self.0.get(&guard) {
crate::internal::poll_get(&cell.cell, cx.waker()).map(Some)
} else {
Poll::Ready(None)
}
}
}
impl<T, C: Deref<Target = AsyncCell<T>>> GuardedCell<T, C> {
pub fn release(mut self) {
self.cancel = None;
}
pub fn set(self, value: T) {
self.inner.set(value);
self.release();
}
pub fn or_set(self, value: T) {
self.inner.or_set(value);
self.release();
}
}
impl<T, C: Deref<Target = AsyncCell<T>>> Deref for GuardedCell<T, C> {
type Target = AsyncCell<T>;
fn deref(&self) -> &AsyncCell<T> {
&*self.inner
}
}
impl<T, C: Deref<Target = AsyncCell<T>>> Drop for GuardedCell<T, C> {
fn drop(&mut self) {
if let Some(cancel) = self.cancel.take() {
self.inner.or_set(cancel);
}
}
}
};
}
#[cfg(not(feature = "no_std"))]
pub mod sync {
use std::sync::{Arc, Weak};
#[cfg(feature = "parking_lot")]
type Mutex<T> = parking_lot::Mutex<crate::internal::DropState<T>>;
#[cfg(not(feature = "parking_lot"))]
type Mutex<T> = std::sync::Mutex<crate::internal::DropState<T>>;
impl_async_cell_part1!("use async_cell::sync::AsyncCell;", Mutex<T>, T, Arc);
#[cfg(feature = "parking_lot")]
impl<T> AsyncCell<T> {
pub const fn new() -> Self {
AsyncCell {
cell: parking_lot::const_mutex(crate::internal::DropState::empty()),
}
}
pub const fn new_with(value: T) -> Self {
AsyncCell {
cell: parking_lot::const_mutex(crate::internal::DropState::full(value)),
}
}
}
#[cfg(not(feature = "parking_lot"))]
impl<T> AsyncCell<T> {
pub const fn new() -> Self {
AsyncCell {
cell: std::sync::Mutex::new(crate::internal::DropState::empty()),
}
}
pub const fn new_with(value: T) -> Self {
AsyncCell {
cell: std::sync::Mutex::new(crate::internal::DropState::full(value)),
}
}
}
impl_async_cell_part2!("use async_cell::sync::AsyncCell;", Arc);
}
pub mod unsync {
use alloc::rc::{Rc, Weak};
impl_async_cell_part1!(
"use async_cell::unsync::AsyncCell;",
core::cell::Cell<crate::internal::DropState<T>>,
T,
Rc
);
impl<T> AsyncCell<T> {
pub const fn new() -> Self {
AsyncCell {
cell: core::cell::Cell::new(crate::internal::DropState::empty()),
}
}
pub const fn new_with(value: T) -> Self {
AsyncCell {
cell: core::cell::Cell::new(crate::internal::DropState::full(value)),
}
}
}
impl_async_cell_part2!("use async_cell::unsync::AsyncCell;", Rc);
}