use std::pin::Pin;
use std::sync::Arc;
use std::task::{Context, Poll};
use crate::darc::handle::{LocalRwDarcReadHandle, LocalRwDarcWriteHandle};
use crate::scheduler::LamellarTask;
use crate::warnings::RuntimeWarning;
use crate::{Darc, LocalLockArray};
use crate::{Dist, LamellarTeamRT, Remote};
use futures_util::Future;
use pin_project::{pin_project, pinned_drop};
use super::{
ArrayOps, LocalLockLocalChunks, LocalLockLocalChunksMut, LocalLockLocalData,
LocalLockMutLocalData, LocalLockReadGuard, LocalLockWriteGuard,
};
#[must_use = " LocalLockArray 'new' handles do nothing unless polled or awaited, or 'spawn()' or 'block()' are called"]
#[pin_project(PinnedDrop)]
#[doc(alias = "Collective")]
pub struct LocalLockArrayHandle<T: Dist + ArrayOps + 'static> {
pub(crate) team: Darc<LamellarTeamRT>,
pub(crate) launched: bool,
#[pin]
pub(crate) creation_future: Pin<Box<dyn Future<Output = LocalLockArray<T>> + Send>>,
}
#[pinned_drop]
impl<T: Dist + ArrayOps + 'static> PinnedDrop for LocalLockArrayHandle<T> {
fn drop(self: Pin<&mut Self>) {
if !self.launched {
RuntimeWarning::DroppedHandle("a LocalLockArrayHandle").print();
}
}
}
impl<T: Dist + ArrayOps + 'static> LocalLockArrayHandle<T> {
pub fn block(mut self) -> LocalLockArray<T> {
self.launched = true;
RuntimeWarning::BlockingCall(
"LocalLockArrayHandle::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<LocalLockArray<T>> {
self.launched = true;
self.team.clone().spawn(self)
}
}
impl<T: Dist + ArrayOps + 'static> Future for LocalLockArrayHandle<T> {
type Output = LocalLockArray<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 = "LocalLockArray lock handles do nothing unless polled or awaited, or 'spawn()' or 'block()' are called"]
#[pin_project(PinnedDrop)] pub struct LocalLockReadHandle<T: Remote> {
pub(crate) array: LocalLockArray<T>,
#[pin]
pub(crate) lock_handle: LocalRwDarcReadHandle<()>,
}
#[pinned_drop]
impl<T: Remote> PinnedDrop for LocalLockReadHandle<T> {
fn drop(self: Pin<&mut Self>) {
if !self.lock_handle.launched {
RuntimeWarning::DroppedHandle("a LocalLockReadHandle").print();
}
}
}
impl<T: Dist> LocalLockReadHandle<T> {
pub(crate) fn new(array: LocalLockArray<T>) -> Self {
Self {
array: array.clone(),
lock_handle: array.lock.read(),
}
}
pub fn block(self) -> LocalLockReadGuard<T> {
RuntimeWarning::BlockingCall(
"LocalLockReadHandle::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<LocalLockReadGuard<T>> {
self.array.lock.darc.clone().inner().rt_team().spawn(self)
}
}
impl<T: Dist> Future for LocalLockReadHandle<T> {
type Output = LocalLockReadGuard<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(LocalLockReadGuard {
array: this.array.clone(),
lock_guard: Arc::new(val),
}),
Poll::Pending => Poll::Pending,
}
}
}
#[must_use = "LocalLockArray lock handles do nothing unless polled or awaited, or 'spawn()' or 'block()' are called"]
#[pin_project(PinnedDrop)] pub struct LocalLockLocalDataHandle<T: Dist> {
pub(crate) array: LocalLockArray<T>,
pub(crate) start_index: usize,
pub(crate) end_index: usize,
#[pin]
pub(crate) lock_handle: LocalRwDarcReadHandle<()>,
}
#[pinned_drop]
impl<T: Dist> PinnedDrop for LocalLockLocalDataHandle<T> {
fn drop(self: Pin<&mut Self>) {
if !self.lock_handle.launched {
RuntimeWarning::DroppedHandle("a LocalLockLocalDataHandle").print();
}
}
}
impl<T: Dist> LocalLockLocalDataHandle<T> {
pub fn block(self) -> LocalLockLocalData<T> {
RuntimeWarning::BlockingCall(
"LocalLockLocalDataHandle::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<LocalLockLocalData<T>> {
self.array.lock.darc.clone().inner().rt_team().spawn(self)
}
}
impl<T: Dist> Future for LocalLockLocalDataHandle<T> {
type Output = LocalLockLocalData<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(LocalLockLocalData {
array: this.array.clone(),
start_index: *this.start_index,
end_index: *this.end_index,
lock_guard: Arc::new(val),
}),
Poll::Pending => Poll::Pending,
}
}
}
#[must_use = "LocalLockArray lock handles do nothing unless polled or awaited, or 'spawn()' or 'block()' are called"]
#[pin_project(PinnedDrop)] pub struct LocalLockWriteHandle<T: Remote> {
pub(crate) array: LocalLockArray<T>,
#[pin]
pub(crate) lock_handle: LocalRwDarcWriteHandle<()>,
}
#[pinned_drop]
impl<T: Remote> PinnedDrop for LocalLockWriteHandle<T> {
fn drop(self: Pin<&mut Self>) {
if !self.lock_handle.launched {
RuntimeWarning::DroppedHandle("a LocalRwDarcWriteHandle").print();
}
}
}
impl<T: Dist> LocalLockWriteHandle<T> {
pub(crate) fn new(array: LocalLockArray<T>) -> Self {
Self {
array: array.clone(),
lock_handle: array.lock.write(),
}
}
pub fn block(self) -> LocalLockWriteGuard<T> {
RuntimeWarning::BlockingCall(
"LocalLockWriteHandle::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<LocalLockWriteGuard<T>> {
self.array.lock.darc.clone().inner().rt_team().spawn(self)
}
}
impl<T: Dist> Future for LocalLockWriteHandle<T> {
type Output = LocalLockWriteGuard<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(LocalLockWriteGuard {
array: this.array.clone(),
lock_guard: val,
}),
Poll::Pending => Poll::Pending,
}
}
}
#[must_use = "LocalLockArray lock handles do nothing unless polled or awaited, or 'spawn()' or 'block()' are called"]
#[pin_project(PinnedDrop)] pub struct LocalLockMutLocalDataHandle<T: Dist> {
pub(crate) array: LocalLockArray<T>,
pub(crate) start_index: usize,
pub(crate) end_index: usize,
#[pin]
pub(crate) lock_handle: LocalRwDarcWriteHandle<()>,
}
#[pinned_drop]
impl<T: Dist> PinnedDrop for LocalLockMutLocalDataHandle<T> {
fn drop(self: Pin<&mut Self>) {
if !self.lock_handle.launched {
RuntimeWarning::DroppedHandle("a LocalLockMutLocalDataHandle").print();
}
}
}
impl<T: Dist> LocalLockMutLocalDataHandle<T> {
pub fn block(self) -> LocalLockMutLocalData<T> {
RuntimeWarning::BlockingCall(
"LocalLockMutLocalDataHandle::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<LocalLockMutLocalData<T>> {
self.array.lock.darc.clone().inner().rt_team().spawn(self)
}
}
impl<T: Dist> Future for LocalLockMutLocalDataHandle<T> {
type Output = LocalLockMutLocalData<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(LocalLockMutLocalData {
array: this.array.clone(),
start_index: *this.start_index,
end_index: *this.end_index,
lock_guard: val,
}),
Poll::Pending => Poll::Pending,
}
}
}
#[must_use = "LocalLockArray lock handles do nothing unless polled or awaited, or 'spawn()' or 'block()' are called"]
#[pin_project(PinnedDrop)] pub struct LocalLockLocalChunksHandle<T: Remote> {
pub(crate) chunk_size: usize,
pub(crate) index: usize, pub(crate) end_index: usize, pub(crate) array: LocalLockArray<T>,
#[pin]
pub(crate) lock_handle: LocalRwDarcReadHandle<()>,
}
#[pinned_drop]
impl<T: Remote> PinnedDrop for LocalLockLocalChunksHandle<T> {
fn drop(self: Pin<&mut Self>) {
if !self.lock_handle.launched {
RuntimeWarning::DroppedHandle("a LocalLockLocalChunksHandle").print();
}
}
}
impl<T: Dist> LocalLockLocalChunksHandle<T> {
pub fn block(self) -> LocalLockLocalChunks<T> {
RuntimeWarning::BlockingCall(
"LocalLockLocalChunksHandle::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<LocalLockLocalChunks<T>> {
self.array.lock.darc.clone().inner().rt_team().spawn(self)
}
}
impl<T: Dist> Future for LocalLockLocalChunksHandle<T> {
type Output = LocalLockLocalChunks<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(LocalLockLocalChunks {
chunk_size: *this.chunk_size,
index: *this.index, end_index: *this.end_index, array: this.array.clone(),
lock_guard: Arc::new(val),
}),
Poll::Pending => Poll::Pending,
}
}
}
#[must_use = "LocalLockArray lock handles do nothing unless polled or awaited, or 'spawn()' or 'block()' are called"]
#[pin_project(PinnedDrop)] pub struct LocalLockLocalChunksMutHandle<T: Remote> {
pub(crate) chunk_size: usize,
pub(crate) index: usize, pub(crate) end_index: usize, pub(crate) array: LocalLockArray<T>,
#[pin]
pub(crate) lock_handle: LocalRwDarcWriteHandle<()>,
}
#[pinned_drop]
impl<T: Remote> PinnedDrop for LocalLockLocalChunksMutHandle<T> {
fn drop(self: Pin<&mut Self>) {
if !self.lock_handle.launched {
RuntimeWarning::DroppedHandle("a LocalLockLocalChunksMutHandle").print();
}
}
}
impl<T: Dist> LocalLockLocalChunksMutHandle<T> {
pub fn block(self) -> LocalLockLocalChunksMut<T> {
RuntimeWarning::BlockingCall(
"LocalLockLocalChunksMutHandle::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<LocalLockLocalChunksMut<T>> {
self.array.lock.darc.clone().inner().rt_team().spawn(self)
}
}
impl<T: Dist> Future for LocalLockLocalChunksMutHandle<T> {
type Output = LocalLockLocalChunksMut<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(LocalLockLocalChunksMut {
chunk_size: *this.chunk_size,
index: *this.index, end_index: *this.end_index, array: this.array.clone(),
lock_guard: Arc::new(val),
}),
Poll::Pending => Poll::Pending,
}
}
}