transfer commit

This commit is contained in:
2023-02-21 18:10:39 +00:00
parent 8387df352b
commit d75add5ea3
10 changed files with 135 additions and 46 deletions

View File

@@ -25,7 +25,7 @@ pub trait Task {
}
fn run_to_completion(&mut self) -> Self::Result {
loop { if let TaskState::Complete(r) = self.run_once() {return r} }
loop { if let TaskState::Complete(r) = self.run_n_times(u64::MAX) {return r} }
}
fn boxed<'a>(self) -> TaskBox<'a, Self::Result> where Self: 'a + Sized { Box::new(self) }

View File

@@ -26,42 +26,65 @@ impl<T: Task, U: Task> TaskPair<T, U> {
}
}
impl<T: Task, U: Task> Task for TaskPair<T, U> {
type Result = (T::Result, U::Result);
fn run_once(&mut self) -> TaskState<Self::Result> {
let TaskPair{ state, tally, l_nice, r_nice } = self;
/// The state machine logic, abstracted from the subtask handling system
macro_rules! main_logic {
($self:ident, $task:ident, $task_runner:expr) => {{
let TaskPair{ state, tally, l_nice, r_nice } = $self;
let ret = process(state, |s| match s {
TaskPairState::Empty => panic!("Generator completed and empty"),
TaskPairState::Left(mut l_task, r_res) => {
match l_task.run_once() {
TaskPairState::Left(mut $task, r_res) => {
match $task_runner {
TaskState::Complete(r) => (TaskPairState::Empty, TaskState::Complete((r, r_res))),
TaskState::Yield => (TaskPairState::Left(l_task, r_res), TaskState::Yield),
TaskState::Yield => (TaskPairState::Left($task, r_res), TaskState::Yield),
}
}
TaskPairState::Right(l_res, mut r_task) => {
match r_task.run_once() {
TaskPairState::Right(l_res, mut $task) => {
match $task_runner {
TaskState::Complete(r) => (TaskPairState::Empty, TaskState::Complete((l_res, r))),
TaskState::Yield => (TaskPairState::Right(l_res, r_task), TaskState::Yield),
TaskState::Yield => (TaskPairState::Right(l_res, $task), TaskState::Yield),
}
}
TaskPairState::Both(mut l_task, mut r_task) => {
TaskPairState::Both(l_task, r_task) => {
let state = if 0 <= *tally {
*tally -= *l_nice as Priority;
match l_task.run_once() {
let mut $task = l_task;
match $task_runner {
TaskState::Complete(r) => TaskPairState::Right(r, r_task),
TaskState::Yield => TaskPairState::Both(l_task, r_task),
TaskState::Yield => TaskPairState::Both($task, r_task),
}
} else {
*tally += *r_nice as Priority;
match r_task.run_once() {
let mut $task = r_task;
match $task_runner {
TaskState::Complete(r) => TaskPairState::Left(l_task, r),
TaskState::Yield => TaskPairState::Both(l_task, r_task),
TaskState::Yield => TaskPairState::Both(l_task, $task),
}
};
(state, TaskState::Yield)
}
});
ret
}};
}
impl<T: Task, U: Task> Task for TaskPair<T, U> {
type Result = (T::Result, U::Result);
fn run_n_times(&mut self, mut count: u64) -> TaskState<Self::Result> {
loop {
if count == 0 {return TaskState::Yield}
match self.state {
TaskPairState::Left(..) | TaskPairState::Right(..) => {
return main_logic!(self, task, task.run_n_times(count));
}
_ => ()
}
if let r@TaskState::Complete(_) = self.run_once() {return r}
count -= 1;
}
}
fn run_once(&mut self) -> TaskState<Self::Result> {
main_logic!(self, task, task.run_once())
}
}

View File

@@ -1,4 +1,4 @@
use std::iter;
use std::{iter, mem};
use itertools::Itertools;
@@ -36,8 +36,9 @@ impl<T: Task> TaskVec<T> {
if self.task_heap.len() <= i {None}
else {self.task_heap[i].as_mut()}
}
/// Returns the tally of the given record. Empty records always sink to the bottom
fn tally(&self, i: usize) -> Nice {
self.task_heap[i].as_ref().map(|e| e.tally).unwrap_or(0)
self.task_heap[i].as_ref().map(|e| e.tally).unwrap_or(Nice::MAX)
}
fn swap(&mut self, a: usize, b: usize) {
self.task_heap.swap(a, b);
@@ -49,7 +50,7 @@ impl<T: Task> TaskVec<T> {
fn normalize(&mut self) {
let shrink_count = self.task_heap.iter().rev().take_while(|e| e.is_none()).count();
let new_len = self.task_heap.len() - shrink_count;
self.task_heap.splice(0..new_len, iter::empty());
self.task_heap.splice(new_len.., iter::empty());
let head = self.entry_mut(0);
let offset = if let Some(e) = head {
let offset = e.tally - 1;
@@ -86,10 +87,43 @@ impl<T: Task> TaskVec<T> {
self.swap(i, mchi);
self.sink(mchi);
}
fn take_results(&mut self) -> Vec<T::Result> {
let mut swap = Vec::new();
mem::swap(&mut self.results, &mut swap);
return swap.into_iter().collect::<Option<_>>()
.expect("Results not full but the heap is empty");
}
fn one_left(&mut self) -> bool {
self.entry(0).is_some() && self.entry(1).is_none() && self.entry(2).is_none()
}
}
impl<T: Task> Task for TaskVec<T> {
type Result = Vec<T::Result>;
fn run_n_times(&mut self, mut count: u64) -> TaskState<Self::Result> {
loop {
if count == 0 {return TaskState::Yield}
if self.one_left() {
let head = &mut self.task_heap[0];
let head_entry = head.as_mut().expect("one_left faulty");
return match head_entry.task.run_n_times(count) {
TaskState::Yield => TaskState::Yield,
TaskState::Complete(r) => {
self.results[head_entry.position] = Some(r);
*head = None;
return TaskState::Complete(self.take_results());
}
}
} else if let r@TaskState::Complete(_) = self.run_once() {return r}
count -= 1;
}
}
fn run_once(&mut self) -> super::TaskState<Self::Result> {
self.normalize();
let head = &mut self.task_heap[0];
let head_entry = head.as_mut().expect("All completed, cannot run further");
head_entry.tally += head_entry.nice;
@@ -98,9 +132,13 @@ impl<T: Task> Task for TaskVec<T> {
self.results[head_entry.position] = Some(r);
*head = None;
self.sink(0);
if self.entry(0).is_some() {
}
if self.entry(0).is_some() { return TaskState::Yield }
TaskState::Complete(self.take_results())
}
TaskState::Yield => {
head_entry.tally += head_entry.nice;
self.sink(0);
TaskState::Yield
}
}
}