use crate::active_set::{ActiveSet, ComplementOf, ComplementWithin};
use crate::warp::Warp;
use core::marker::PhantomData;
pub trait WriteState: crate::active_set::sealed::Sealed {}
#[derive(Debug, Clone, Copy)]
pub struct Unwritten;
#[allow(private_interfaces)]
impl crate::active_set::sealed::Sealed for Unwritten {
fn _sealed() -> crate::active_set::sealed::SealToken {
crate::active_set::sealed::SealToken
}
}
impl WriteState for Unwritten {}
#[derive(Debug, Clone, Copy)]
pub struct PartialWrite<S: ActiveSet> {
_phantom: PhantomData<S>,
}
#[allow(private_interfaces)]
impl<S: ActiveSet> crate::active_set::sealed::Sealed for PartialWrite<S> {
fn _sealed() -> crate::active_set::sealed::SealToken {
crate::active_set::sealed::SealToken
}
}
impl<S: ActiveSet> WriteState for PartialWrite<S> {}
#[derive(Debug, Clone, Copy)]
pub struct FullWrite;
#[allow(private_interfaces)]
impl crate::active_set::sealed::Sealed for FullWrite {
fn _sealed() -> crate::active_set::sealed::SealToken {
crate::active_set::sealed::SealToken
}
}
impl WriteState for FullWrite {}
#[derive(Debug, Clone, Copy)]
pub struct Fenced;
#[allow(private_interfaces)]
impl crate::active_set::sealed::Sealed for Fenced {
fn _sealed() -> crate::active_set::sealed::SealToken {
crate::active_set::sealed::SealToken
}
}
impl WriteState for Fenced {}
#[must_use = "GlobalRegion tracks write progress — dropping it loses the write-state proof"]
pub struct GlobalRegion<'r, S: WriteState> {
_brand: PhantomData<fn(&'r ()) -> &'r ()>,
_state: PhantomData<S>,
}
impl GlobalRegion<'_, Unwritten> {
pub fn with_region<R>(f: impl for<'r> FnOnce(GlobalRegion<'r, Unwritten>) -> R) -> R {
f(GlobalRegion {
_brand: PhantomData,
_state: PhantomData,
})
}
}
impl<'r> GlobalRegion<'r, Unwritten> {
pub fn split(self) -> (GlobalRegion<'r, Unwritten>, GlobalRegion<'r, Unwritten>) {
(
GlobalRegion {
_brand: PhantomData,
_state: PhantomData,
},
GlobalRegion {
_brand: PhantomData,
_state: PhantomData,
},
)
}
}
impl<S: ActiveSet> Warp<S> {
pub fn global_store<'r>(
self,
_region: GlobalRegion<'r, Unwritten>,
) -> (Self, GlobalRegion<'r, PartialWrite<S>>) {
(
self,
GlobalRegion {
_brand: PhantomData,
_state: PhantomData,
},
)
}
pub fn global_store_complement<'r, S2: ActiveSet>(
self,
_region: GlobalRegion<'r, PartialWrite<S2>>,
) -> (Self, GlobalRegion<'r, FullWrite>)
where
S: ComplementOf<S2>,
{
(
self,
GlobalRegion {
_brand: PhantomData,
_state: PhantomData,
},
)
}
}
pub fn merge_writes<'r, S1, S2>(
_a: GlobalRegion<'r, PartialWrite<S1>>,
_b: GlobalRegion<'r, PartialWrite<S2>>,
) -> GlobalRegion<'r, FullWrite>
where
S1: ComplementOf<S2>,
S2: ActiveSet,
{
GlobalRegion {
_brand: PhantomData,
_state: PhantomData,
}
}
pub fn merge_writes_within<'r, S1, S2, P>(
_a: GlobalRegion<'r, PartialWrite<S1>>,
_b: GlobalRegion<'r, PartialWrite<S2>>,
) -> GlobalRegion<'r, PartialWrite<P>>
where
S1: ComplementWithin<S2, P>,
S2: ActiveSet,
P: ActiveSet,
{
GlobalRegion {
_brand: PhantomData,
_state: PhantomData,
}
}
pub fn threadfence(_proof: GlobalRegion<FullWrite>) -> GlobalRegion<Fenced> {
GlobalRegion {
_brand: PhantomData,
_state: PhantomData,
}
}
impl GlobalRegion<'_, Fenced> {
pub fn read<T: Default>(&self) -> T {
T::default() }
}
#[cfg(test)]
mod tests {
use super::*;
use crate::active_set::*;
#[test]
fn test_full_fence_protocol() {
GlobalRegion::with_region(|region| {
let warp: Warp<All> = Warp::new();
let (evens, odds) = warp.diverge_even_odd();
let (evens, partial_even) = evens.global_store(region);
let (odds, full) = odds.global_store_complement(partial_even);
let _merged: Warp<All> = crate::merge(evens, odds);
let fenced = threadfence(full);
let _val: i32 = fenced.read();
});
}
#[test]
fn test_merge_writes_same_region() {
GlobalRegion::with_region(|region| {
let (r1, r2) = region.split();
let warp: Warp<All> = Warp::new();
let (evens, odds) = warp.diverge_even_odd();
let (_evens, partial_even) = evens.global_store(r1);
let (_odds, partial_odd) = odds.global_store(r2);
let full = merge_writes(partial_even, partial_odd);
let _fenced = threadfence(full);
});
}
#[test]
fn test_nested_fence_protocol() {
GlobalRegion::with_region(|region| {
let (r_odd, r_nested) = region.split();
let (r_el, r_eh) = r_nested.split();
let warp: Warp<All> = Warp::new();
let (evens, odds) = warp.diverge_even_odd();
let (even_low, even_high) = evens.diverge_halves();
let (_odds, partial_odd) = odds.global_store(r_odd);
let (_el, partial_el) = even_low.global_store(r_el);
let (_eh, partial_eh) = even_high.global_store(r_eh);
let even_partial: GlobalRegion<PartialWrite<Even>> =
merge_writes_within(partial_el, partial_eh);
let full = merge_writes(even_partial, partial_odd);
let _fenced = threadfence(full);
});
}
#[test]
fn test_global_store_complement_same_region() {
GlobalRegion::with_region(|region| {
let warp: Warp<All> = Warp::new();
let (evens, odds) = warp.diverge_even_odd();
let (_evens, partial) = evens.global_store(region);
let (_odds, full) = odds.global_store_complement(partial);
let _fenced = threadfence(full);
});
}
#[test]
fn test_with_region_returns_value() {
let result = GlobalRegion::with_region(|region| {
let warp: Warp<All> = Warp::new();
let (evens, odds) = warp.diverge_even_odd();
let (_evens, partial) = evens.global_store(region);
let (_odds, full) = odds.global_store_complement(partial);
let fenced = threadfence(full);
fenced.read::<i32>()
});
assert_eq!(result, 0); }
#[test]
fn test_split_preserves_region_identity() {
GlobalRegion::with_region(|region| {
let (a, b) = region.split();
let (a1, a2) = a.split();
let warp: Warp<All> = Warp::new();
let (evens, odds) = warp.diverge_even_odd();
let (even_low, even_high) = evens.diverge_halves();
let (_el, p_el) = even_low.global_store(a1);
let (_eh, p_eh) = even_high.global_store(a2);
let (_odds, p_odd) = odds.global_store(b);
let even_partial: GlobalRegion<PartialWrite<Even>> = merge_writes_within(p_el, p_eh);
let full = merge_writes(even_partial, p_odd);
let _fenced = threadfence(full);
});
}
}