use crate::synca::Entry;
use crate::valtron::{
BoxedExecutionEngine, BoxedExecutionIterator, Ctx, ExecutionIterator, SpawnInfo, State,
};
#[allow(dead_code)]
pub(crate) struct LinkedParentChildTaskInner {
pub info: SpawnInfo,
pub parent: Option<BoxedExecutionIterator>,
pub child: Option<BoxedExecutionIterator>,
pub pending_parent_state: Option<State>,
}
pub struct DualSequeunceChildAndParentLinkedTask(LinkedParentChildTaskInner);
impl DualSequeunceChildAndParentLinkedTask {
#[must_use]
pub fn new(
info: SpawnInfo,
parent: BoxedExecutionIterator,
child: BoxedExecutionIterator,
) -> Self {
Self(LinkedParentChildTaskInner {
info,
parent: Some(parent),
child: Some(child),
pending_parent_state: None,
})
}
}
impl ExecutionIterator for DualSequeunceChildAndParentLinkedTask {
fn next(&mut self, parent_id: Entry, engine: BoxedExecutionEngine, ctx: Ctx) -> Option<State> {
if let Some(pending) = self.0.pending_parent_state.take() {
return Some(pending);
}
if let Some(mut child) = self.0.child.take() {
if let Some(child_state) = child.next(parent_id, engine.boxed_engine(), ctx.clone()) {
if child_state != State::Done {
self.0.child = Some(child);
if let Some(mut parent) = self.0.parent.take() {
if let Some(parent_state) = parent.next(parent_id, engine, ctx.clone()) {
let needs_propagation = matches!(
parent_state,
State::Wait
| State::Pending(Some(_))
| State::SpawnFinished(_)
| State::Panicked
| State::Reschedule
);
let parent_is_done = parent_state == State::Done;
if needs_propagation {
self.0.pending_parent_state = Some(parent_state);
}
if !parent_is_done {
self.0.parent = Some(parent);
}
}
}
return Some(child_state);
}
}
}
if let Some(mut parent) = self.0.parent.take() {
if let Some(parent_state) = parent.next(parent_id, engine, ctx.clone()) {
if parent_state != State::Done {
self.0.parent = Some(parent);
}
return Some(parent_state);
}
}
None
}
}
pub struct FinishChildBeforeParentTask(LinkedParentChildTaskInner);
impl FinishChildBeforeParentTask {
#[must_use]
pub fn new(
info: SpawnInfo,
parent: BoxedExecutionIterator,
child: BoxedExecutionIterator,
) -> Self {
Self(LinkedParentChildTaskInner {
info,
parent: Some(parent),
child: Some(child),
pending_parent_state: None,
})
}
}
impl ExecutionIterator for FinishChildBeforeParentTask {
fn next(&mut self, parent_id: Entry, engine: BoxedExecutionEngine, ctx: Ctx) -> Option<State> {
if let Some(mut child) = self.0.child.take() {
if let Some(child_state) = child.next(parent_id, engine.boxed_engine(), ctx.clone()) {
if child_state != State::Done {
self.0.child = Some(child);
return Some(child_state);
}
}
}
if let Some(mut parent) = self.0.parent.take() {
if let Some(parent_state) = parent.next(parent_id, engine, ctx.clone()) {
self.0.parent = Some(parent);
return Some(parent_state);
}
}
None
}
}