use crate::{self as cubecl, prelude::*};
use cubecl_ir::{
dialect::pending::{CommitOp, ReadyOp, WaitOp},
types::pending::{AsyncGroup, WaitUntil},
};
use cubecl_macros::{CubeTypeMut, intrinsic};
use pliron::value::Value;
#[derive(CubeType, CubeTypeMut)]
#[must_use = "the work runs on until it is waited on"]
pub struct Pending<T: PendingValue> {
#[allow(unused)]
pub(crate) value: T,
pub(crate) token: GroupToken,
}
#[cube]
pub trait PendingValue: CubeType + Sized {
fn wait_for(pending: Pending<Self>) -> Self;
}
#[cube]
impl<T: PendingValue> Pending<T> {
pub fn wait(self) -> T {
T::wait_for(self)
}
}
#[cube]
impl PendingValue for () {
fn wait_for(pending: Pending<Self>) -> Self {
pending.token.wait();
}
}
#[cube]
impl Pending<()> {
pub fn wait_complete(self) {
self.token.wait_until(comptime![WaitUntil::Complete]);
}
}
impl Copy for PendingExpand<()> {}
impl<T: PendingValue<ExpandType: Clone>> Clone for PendingExpand<T> {
fn clone(&self) -> Self {
Self {
value: self.value.clone(),
token: self.token,
}
}
}
impl Copy for Pending<()> {}
impl<T: PendingValue + Clone> Clone for Pending<T> {
fn clone(&self) -> Self {
Self {
value: self.value.clone(),
token: self.token,
}
}
}
impl<T: PendingValue> PendingExpand<T> {
pub(crate) fn commit(scope: &Scope, group: AsyncGroup, value: T::ExpandType) -> Self {
Self {
value,
token: GroupToken::commit(scope, group),
}
}
pub(crate) fn ready(scope: &Scope, group: AsyncGroup, value: T::ExpandType) -> Self {
let op = ReadyOp::new(scope.ctx_mut(), group);
Self {
value,
token: scope.register_with_result(&op).into(),
}
}
}
#[derive(Clone, Copy)]
pub(crate) struct GroupToken;
pub(crate) type GroupTokenExpand = NativeExpand<GroupToken>;
impl GroupToken {
pub(crate) fn commit(scope: &Scope, group: AsyncGroup) -> NativeExpand<GroupToken> {
let op = CommitOp::new(scope.ctx_mut(), group);
scope.register_with_result(&op).into()
}
}
#[cube]
impl GroupToken {
pub(crate) fn wait(&self) {
self.wait_until(comptime![WaitUntil::Released]);
}
#[allow(unused_variables)]
pub(crate) fn wait_until(&self, #[comptime] until: WaitUntil) {
intrinsic!(|scope| {
let token = self.read_value(scope);
scope.register(&WaitOp::new(scope.ctx_mut(), token, until));
})
}
}
impl CubeType for GroupToken {
type ExpandType = NativeExpand<GroupToken>;
}
impl CubeDebug for GroupToken {}
impl ReadValue for NativeExpand<GroupToken> {
fn read_value(&self, scope: &Scope) -> Value {
self.expand.read_value(scope)
}
}
impl NativeAssign for GroupToken {}
impl AsMutExpand for NativeExpand<GroupToken> {
fn __expand_ref_mut_method(&mut self, _: &Scope) -> &mut Self {
self
}
}