use core::pin::Pin;
use core::task::{Context, Poll};
use derive_more::{Debug, Into};
use crate::layout::SharedLayout;
use crate::sync::{WaitGroupLayoutExt, WaitGroupWrapper};
use crate::twin_ref::{ClonableTwinRef, TwinRef};
#[cfg(feature = "compact-mono")]
type MonoLayout = crate::layout::MonoLayout;
#[cfg(not(feature = "compact-mono"))]
type MonoLayout = crate::layout::SharedLayout;
#[must_use]
#[derive(Debug)]
pub struct WaitGroup(#[debug("done: {}", _0.is_done())] WaitGroupWrapper<TwinRef<SharedLayout>>);
#[must_use]
#[derive(Debug)]
pub struct MonoWaitGroup(#[debug("done: {}", _0.is_done())] WaitGroupWrapper<TwinRef<MonoLayout>>);
#[must_use]
#[derive(Clone, Debug)]
pub struct GroupToken(
#[allow(unused)]
#[debug("done: {}", _0.is_done())]
ClonableTwinRef<SharedLayout>,
);
#[must_use]
#[derive(Debug)]
pub struct MonoGroupToken(#[debug("done: {}", _0.is_done())] TwinRef<MonoLayout>);
#[must_use]
#[derive(Debug, Into)]
pub struct GroupTokenFactory(GroupToken);
impl WaitGroup {
pub fn new() -> (Self, GroupTokenFactory) {
let inner = SharedLayout::new();
let (wg, token) = TwinRef::new_clonable(inner);
(
Self(WaitGroupWrapper::new(wg)),
GroupTokenFactory(GroupToken(token)),
)
}
#[inline]
pub fn is_done(&self) -> bool {
self.0.is_done()
}
}
impl MonoWaitGroup {
pub fn new() -> (Self, MonoGroupToken) {
let inner = MonoLayout::new();
let (wg, token) = TwinRef::new_mono(inner);
(Self(WaitGroupWrapper::new(wg)), MonoGroupToken(token))
}
#[inline]
pub fn is_done(&self) -> bool {
self.0.is_done()
}
}
impl Future for WaitGroup {
type Output = ();
#[inline]
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
Pin::new(&mut self.0).poll(cx)
}
}
impl Future for MonoWaitGroup {
type Output = ();
#[inline]
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
Pin::new(&mut self.0).poll(cx)
}
}
impl GroupTokenFactory {
#[inline]
pub fn release(self) {
drop(self);
}
#[inline]
pub fn into_token(self) -> GroupToken {
self.0
}
#[inline]
pub fn scope<T, F: FnOnce(GroupToken) -> T>(self, func: F) -> T {
func(self.into_token())
}
}
impl GroupToken {
#[inline]
pub fn release(self) {
drop(self);
}
}
impl MonoGroupToken {
#[inline]
pub fn release(self) {
drop(self);
}
#[inline]
pub fn into_token(self) -> Self {
self
}
#[inline]
pub fn scope<T, F: FnOnce(MonoGroupToken) -> T>(self, func: F) -> T {
func(self.into_token())
}
}
impl Drop for MonoGroupToken {
#[inline]
fn drop(&mut self) {
unsafe {
self.0.send_done();
}
}
}