use std::pin::Pin;
use std::task::{Context, Poll};
use crate::darc::handle::{
GlobalRwDarcCollectiveWriteHandle, GlobalRwDarcReadHandle, GlobalRwDarcWriteHandle,
};
use crate::scheduler::LamellarTask;
use crate::warnings::RuntimeWarning;
use crate::{Darc, GlobalLockArray};
use crate::{Dist, LamellarTeamRT, Remote};
use futures_util::Future;
use pin_project::{pin_project, pinned_drop};
use super::{
ArrayOps, GlobalLockCollectiveMutLocalData, GlobalLockLocalData, GlobalLockMutLocalData,
GlobalLockReadGuard, GlobalLockWriteGuard,
};
#[must_use = " GlobalLockArray 'new' handles do nothing unless polled or awaited, or 'spawn()' or 'block()' are called"]
#[pin_project(PinnedDrop)]
#[doc(alias = "Collective")]
pub struct GlobalLockArrayHandle<T: Dist + ArrayOps + 'static> {
pub(crate) team: Darc<LamellarTeamRT>,
pub(crate) launched: bool,
#[pin]
pub(crate) creation_future: Pin<Box<dyn Future<Output = GlobalLockArray<T>> + Send>>,
}
#[pinned_drop]
impl<T: Dist + ArrayOps + 'static> PinnedDrop for GlobalLockArrayHandle<T> {
fn drop(self: Pin<&mut Self>) {
if !self.launched {
RuntimeWarning::DroppedHandle("a GlobalLockArrayHandle").print();
}
}
}
impl<T: Dist + ArrayOps + 'static> GlobalLockArrayHandle<T> {
pub fn block(mut self) -> GlobalLockArray<T> {
self.launched = true;
RuntimeWarning::BlockingCall(
"GlobalLockArrayHandle::block",
"<handle>.spawn() or<handle>.await",
)
.print();
self.team.clone().block_on(self)
}
#[must_use = "this function returns a future [LamellarTask] used to poll for completion. Call '.await' on the returned future in an async context or '.block()' in a non async context. Alternatively it may be acceptable to call '.block()' instead of 'spawn()' on this handle"]
pub fn spawn(mut self) -> LamellarTask<GlobalLockArray<T>> {
self.launched = true;
self.team.clone().spawn(self)
}
}
impl<T: Dist + ArrayOps + 'static> Future for GlobalLockArrayHandle<T> {
type Output = GlobalLockArray<T>;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
self.launched = true;
let mut this = self.project();
this.creation_future.as_mut().poll(cx)
}
}
#[must_use = "GlobalLockArray lock handles do nothing unless polled or awaited, or 'spawn()' or 'block()' are called"]
#[pin_project] pub struct GlobalLockReadHandle<T: Remote> {
pub(crate) array: GlobalLockArray<T>,
#[pin]
pub(crate) lock_handle: GlobalRwDarcReadHandle<()>,
}
impl<T: Dist> GlobalLockReadHandle<T> {
pub(crate) fn new(array: GlobalLockArray<T>) -> Self {
Self {
array: array.clone(),
lock_handle: array.lock.read(),
}
}
pub fn block(self) -> GlobalLockReadGuard<T> {
RuntimeWarning::BlockingCall(
"GlobalLockReadHandle::block",
"<handle>.spawn() or<handle>.await",
)
.print();
self.array
.lock
.darc
.clone()
.inner()
.rt_team()
.scheduler
.block_on(self)
}
#[must_use = "this function returns a future [LamellarTask] used to poll for completion. Call '.await' on the returned future in an async context or '.block()' in a non async context. Alternatively it may be acceptable to call '.block()' instead of 'spawn()' on this handle"]
pub fn spawn(self) -> LamellarTask<GlobalLockReadGuard<T>> {
self.array.lock.darc.clone().inner().rt_team().spawn(self)
}
}
impl<T: Dist> Future for GlobalLockReadHandle<T> {
type Output = GlobalLockReadGuard<T>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.project();
match this.lock_handle.poll(cx) {
Poll::Ready(val) => Poll::Ready(GlobalLockReadGuard {
array: this.array.clone(),
lock_guard: val,
}),
Poll::Pending => Poll::Pending,
}
}
}
#[must_use = "GlobalLockArray lock handles do nothing unless polled or awaited, or 'spawn()' or 'block()' are called"]
#[pin_project] pub struct GlobalLockLocalDataHandle<T: Dist> {
pub(crate) array: GlobalLockArray<T>,
pub(crate) start_index: usize,
pub(crate) end_index: usize,
#[pin]
pub(crate) lock_handle: GlobalRwDarcReadHandle<()>,
}
impl<T: Dist> GlobalLockLocalDataHandle<T> {
pub fn block(self) -> GlobalLockLocalData<T> {
RuntimeWarning::BlockingCall(
"GlobalLockLocalDataHandle::block",
"<handle>.spawn() or<handle>.await",
)
.print();
self.array
.lock
.darc
.clone()
.inner()
.rt_team()
.scheduler
.block_on(self)
}
#[must_use = "this function returns a future [LamellarTask] used to poll for completion. Call '.await' on the returned future in an async context or '.block()' in a non async context. Alternatively it may be acceptable to call '.block()' instead of 'spawn()' on this handle"]
pub fn spawn(self) -> LamellarTask<GlobalLockLocalData<T>> {
self.array.lock.darc.clone().inner().rt_team().spawn(self)
}
}
impl<T: Dist> Future for GlobalLockLocalDataHandle<T> {
type Output = GlobalLockLocalData<T>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.project();
match this.lock_handle.poll(cx) {
Poll::Ready(val) => Poll::Ready(GlobalLockLocalData {
array: this.array.clone(),
start_index: *this.start_index,
end_index: *this.end_index,
lock_guard: val,
}),
Poll::Pending => Poll::Pending,
}
}
}
#[must_use = "GlobalLockArray lock handles do nothing unless polled or awaited, or 'spawn()' or 'block()' are called"]
#[pin_project] pub struct GlobalLockWriteHandle<T: Remote> {
pub(crate) array: GlobalLockArray<T>,
#[pin]
pub(crate) lock_handle: GlobalRwDarcWriteHandle<()>,
}
impl<T: Dist> GlobalLockWriteHandle<T> {
pub(crate) fn new(array: GlobalLockArray<T>) -> Self {
Self {
array: array.clone(),
lock_handle: array.lock.write(),
}
}
pub fn block(self) -> GlobalLockWriteGuard<T> {
RuntimeWarning::BlockingCall(
"GlobalLockWriteHandle::block",
"<handle>.spawn() or<handle>.await",
)
.print();
self.array
.lock
.darc
.clone()
.inner()
.rt_team()
.scheduler
.block_on(self)
}
#[must_use = "this function returns a future [LamellarTask] used to poll for completion. Call '.await' on the returned future in an async context or '.block()' in a non async context. Alternatively it may be acceptable to call '.block()' instead of 'spawn()' on this handle"]
pub fn spawn(self) -> LamellarTask<GlobalLockWriteGuard<T>> {
self.array.lock.darc.clone().inner().rt_team().spawn(self)
}
}
impl<T: Dist> Future for GlobalLockWriteHandle<T> {
type Output = GlobalLockWriteGuard<T>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.project();
match this.lock_handle.poll(cx) {
Poll::Ready(val) => Poll::Ready(GlobalLockWriteGuard {
array: this.array.clone(),
lock_guard: val,
}),
Poll::Pending => Poll::Pending,
}
}
}
#[must_use = "GlobalLockArray lock handles do nothing unless polled or awaited, or 'spawn()' or 'block()' are called"]
#[pin_project] pub struct GlobalLockMutLocalDataHandle<T: Dist> {
pub(crate) array: GlobalLockArray<T>,
pub(crate) start_index: usize,
pub(crate) end_index: usize,
#[pin]
pub(crate) lock_handle: GlobalRwDarcWriteHandle<()>,
}
impl<T: Dist> GlobalLockMutLocalDataHandle<T> {
pub fn block(self) -> GlobalLockMutLocalData<T> {
RuntimeWarning::BlockingCall(
"GlobalLockMutLocalDataHandle::block",
"<handle>.spawn() or<handle>.await",
)
.print();
self.array
.lock
.darc
.clone()
.inner()
.rt_team()
.scheduler
.block_on(self)
}
#[must_use = "this function returns a future [LamellarTask] used to poll for completion. Call '.await' on the returned future in an async context or '.block()' in a non async context. Alternatively it may be acceptable to call '.block()' instead of 'spawn()' on this handle"]
pub fn spawn(self) -> LamellarTask<GlobalLockMutLocalData<T>> {
self.array.lock.darc.clone().inner().rt_team().spawn(self)
}
}
impl<T: Dist> Future for GlobalLockMutLocalDataHandle<T> {
type Output = GlobalLockMutLocalData<T>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.project();
match this.lock_handle.poll(cx) {
Poll::Ready(val) => Poll::Ready(GlobalLockMutLocalData {
array: this.array.clone(),
start_index: *this.start_index,
end_index: *this.end_index,
lock_guard: val,
}),
Poll::Pending => Poll::Pending,
}
}
}
#[must_use = "GlobalLockArray lock handles do nothing unless polled or awaited, or 'spawn()' or 'block()' are called"]
#[pin_project] pub struct GlobalLockCollectiveMutLocalDataHandle<T: Dist> {
pub(crate) array: GlobalLockArray<T>,
pub(crate) start_index: usize,
pub(crate) end_index: usize,
#[pin]
pub(crate) lock_handle: GlobalRwDarcCollectiveWriteHandle<()>,
}
impl<T: Dist> GlobalLockCollectiveMutLocalDataHandle<T> {
pub fn block(self) -> GlobalLockCollectiveMutLocalData<T> {
RuntimeWarning::BlockingCall(
"GlobalLockCollectiveMutLocalData::block",
"<handle>.spawn() or<handle>.await",
)
.print();
self.array
.lock
.darc
.clone()
.inner()
.rt_team()
.scheduler
.block_on(self)
}
#[must_use = "this function returns a future [LamellarTask] used to poll for completion. Call '.await' on the returned future in an async context or '.block()' in a non async context. Alternatively it may be acceptable to call '.block()' instead of 'spawn()' on this handle"]
pub fn spawn(self) -> LamellarTask<GlobalLockCollectiveMutLocalData<T>> {
self.array.lock.darc.clone().inner().rt_team().spawn(self)
}
}
impl<T: Dist> Future for GlobalLockCollectiveMutLocalDataHandle<T> {
type Output = GlobalLockCollectiveMutLocalData<T>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.project();
match this.lock_handle.poll(cx) {
Poll::Ready(val) => Poll::Ready(GlobalLockCollectiveMutLocalData {
array: this.array.clone(),
start_index: *this.start_index,
end_index: *this.end_index,
_lock_guard: val,
}),
Poll::Pending => Poll::Pending,
}
}
}