transfer commit
This commit is contained in:
@@ -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) }
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user