This adjusts the process of the compute thread.
The compute thread now implements the state machine using the match statement.
This commit is contained in:
parent
bc4ed6d0bc
commit
7bd5378500
@ -1,4 +1,5 @@
|
|||||||
use std::collections::binary_heap::BinaryHeap;
|
use std::collections::binary_heap::BinaryHeap;
|
||||||
|
use std::vec::Drain;
|
||||||
use std::ops::DerefMut;
|
use std::ops::DerefMut;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::sync::mpsc::{Receiver, Sender, TryRecvError};
|
use std::sync::mpsc::{Receiver, Sender, TryRecvError};
|
||||||
@ -186,99 +187,182 @@ impl Thread for ComputeThread
|
|||||||
fn process(&mut self)
|
fn process(&mut self)
|
||||||
{
|
{
|
||||||
let mut check_messages: bool;
|
let mut check_messages: bool;
|
||||||
let mut task_completed: bool;
|
|
||||||
|
|
||||||
// Run this thread until the scheduler decides
|
// Run this thread until the scheduler decides
|
||||||
// to shut it down.
|
// to shut it down.
|
||||||
self.change_state(ThreadState::Idle);
|
|
||||||
while self.continue_running == true
|
while self.continue_running == true
|
||||||
{
|
{
|
||||||
// No task was recently completed.
|
|
||||||
task_completed = false;
|
|
||||||
|
|
||||||
// Make sure that this thread has a Task
|
|
||||||
// to currently work on.
|
|
||||||
match self.current_task
|
|
||||||
{
|
|
||||||
Some(ref mut task) =>
|
|
||||||
{
|
|
||||||
println!("Task FOUND. Calling process.");
|
|
||||||
// Process the task this thread is
|
|
||||||
// currently working on.
|
|
||||||
task.process(&mut self.spawner);
|
|
||||||
|
|
||||||
match task.get_state()
|
|
||||||
{
|
|
||||||
TaskState::Finished =>
|
|
||||||
{
|
|
||||||
task_completed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
_ =>
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
None =>
|
|
||||||
{
|
|
||||||
println!("Task NOT found. Looking for new task.");
|
|
||||||
// Try to get a task to work on.
|
|
||||||
self.retrieve_task();
|
|
||||||
match self.current_task
|
|
||||||
{
|
|
||||||
Some(_) =>
|
|
||||||
{
|
|
||||||
println!("Task RETRIEVED.");
|
|
||||||
// We have a task to work on, so switch to
|
|
||||||
// a Processing state.
|
|
||||||
self.change_state(ThreadState::Processing);
|
|
||||||
}
|
|
||||||
|
|
||||||
None =>
|
|
||||||
{
|
|
||||||
println!("Taskless. Idling thread.");
|
|
||||||
// If we don't have a task to process,
|
|
||||||
// then we may need to switch over to
|
|
||||||
// an idle state.
|
|
||||||
match self.state
|
match self.state
|
||||||
{
|
{
|
||||||
|
ThreadState::Starting =>
|
||||||
|
{
|
||||||
|
// The starting state can only lead to the
|
||||||
|
// idle state, and does so directly.
|
||||||
|
self.change_state(ThreadState::Idle);
|
||||||
|
}
|
||||||
|
|
||||||
ThreadState::Idle =>
|
ThreadState::Idle =>
|
||||||
{
|
{
|
||||||
// The thread is already sitting idle.
|
// Check to see if we have a task.
|
||||||
}
|
if self.current_task.is_some() == true
|
||||||
|
|
||||||
_ =>
|
|
||||||
{
|
{
|
||||||
// There is nothing for this thread
|
// Why are we idling? We should not get here.
|
||||||
// to process, so mark the thread as idle.
|
debug!("Thread is idling when it should be processing.");
|
||||||
self.change_state(ThreadState::Idle);
|
self.change_state(ThreadState::Processing);
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check to see if the task this thread
|
|
||||||
// was processing was completed.
|
|
||||||
if task_completed == true
|
|
||||||
{
|
{
|
||||||
println!("Task completed.");
|
// We need to check if there is a task that
|
||||||
self.current_task = None;
|
// we should be processing.
|
||||||
self.change_state(ThreadState::Idle);
|
self.retrieve_task();
|
||||||
|
if self.current_task.is_some() == true
|
||||||
|
{
|
||||||
|
// We got a new task to process,
|
||||||
|
// so switch to the Processing state.
|
||||||
|
self.change_state(ThreadState::Processing);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sleep the thread so that other threads
|
|
||||||
// get a chance to run
|
|
||||||
::std::thread::sleep(Duration::new(0, 100));
|
|
||||||
|
|
||||||
// Check to see if this thread should be shutdown.
|
// Check to see if this thread should be shutdown.
|
||||||
self.process_shutdown_messages();
|
self.process_shutdown_messages();
|
||||||
}
|
}
|
||||||
|
|
||||||
// This thread is finished.
|
ThreadState::Processing =>
|
||||||
println!("Shutting down thread.");
|
{
|
||||||
self.change_state(ThreadState::Finished);
|
let mut is_task_finished: bool;
|
||||||
|
let mut has_spawned_children: bool;
|
||||||
|
let mut tasks: Vec<Box<TaskStateMachine>>;
|
||||||
|
let mut child_task: Option<Box<TaskStateMachine>>;
|
||||||
|
|
||||||
|
// Check to see if we have a task. The match statement
|
||||||
|
// makes this easier to handle, but because it borrows
|
||||||
|
// the current task we need to mark the action to take
|
||||||
|
// and then handle it outside of the match statement
|
||||||
|
// if it changes the current task.
|
||||||
|
is_task_finished = false;
|
||||||
|
has_spawned_children = false;
|
||||||
|
match self.current_task
|
||||||
|
{
|
||||||
|
Some(ref mut task) =>
|
||||||
|
{
|
||||||
|
// Process the task this thread is
|
||||||
|
// currently working on.
|
||||||
|
is_task_finished = task.process(&mut self.spawner);
|
||||||
|
|
||||||
|
// If the task is not finished then
|
||||||
|
// check to see if any child tasks
|
||||||
|
// were spawned.
|
||||||
|
if is_task_finished == false
|
||||||
|
{
|
||||||
|
if self.spawner.has_child_tasks() == true
|
||||||
|
{
|
||||||
|
has_spawned_children = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None =>
|
||||||
|
{
|
||||||
|
// Why are we processing? We should not get here.
|
||||||
|
debug!("Thread is processing when it should be idling.");
|
||||||
|
self.change_state(ThreadState::Idle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there are any sibling tasks that were
|
||||||
|
// spawned then add them to the queue.
|
||||||
|
if self.spawner.has_sibling_tasks() == true
|
||||||
|
{
|
||||||
|
tasks = self.spawner.retrieve_sibling_tasks();
|
||||||
|
while tasks.is_empty() == false
|
||||||
|
{
|
||||||
|
child_task = tasks.pop();
|
||||||
|
match child_task
|
||||||
|
{
|
||||||
|
Some(task) =>
|
||||||
|
{
|
||||||
|
self.queue_task(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
None =>
|
||||||
|
{
|
||||||
|
debug!("Queueing a sibling task that \
|
||||||
|
did not exist.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for any actions that need to be taken.
|
||||||
|
if is_task_finished == true
|
||||||
|
{
|
||||||
|
// If the task was finished then it can be
|
||||||
|
// dropped and this thread can go to an idle state.
|
||||||
|
self.current_task = None;
|
||||||
|
self.change_state(ThreadState::Idle);
|
||||||
|
}
|
||||||
|
else if has_spawned_children == true
|
||||||
|
{
|
||||||
|
// The current task is not finished so
|
||||||
|
// queue any child tasks that were spawned.
|
||||||
|
tasks = self.spawner.retrieve_child_tasks();
|
||||||
|
while tasks.is_empty() == false
|
||||||
|
{
|
||||||
|
child_task = tasks.pop();
|
||||||
|
match child_task
|
||||||
|
{
|
||||||
|
Some(task) =>
|
||||||
|
{
|
||||||
|
self.queue_task(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
None =>
|
||||||
|
{
|
||||||
|
debug!("Queueing a child task that did not exist.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check to see if this thread should be shutdown.
|
||||||
|
self.process_shutdown_messages();
|
||||||
|
}
|
||||||
|
|
||||||
|
ThreadState::Finished =>
|
||||||
|
{
|
||||||
|
let task: Option<Box<TaskStateMachine>>;
|
||||||
|
|
||||||
|
// The thread has been put into a finished state.
|
||||||
|
// This means that the thread should exit its loop.
|
||||||
|
info!("Shutting down thread.");
|
||||||
|
self.continue_running = false;
|
||||||
|
|
||||||
|
// Also, if the thread is currently working on
|
||||||
|
// an unfinished task then we should requeue it.
|
||||||
|
self.current_task = None;
|
||||||
|
/*
|
||||||
|
task = self.current_task;
|
||||||
|
match task
|
||||||
|
{
|
||||||
|
Some(old_task) =>
|
||||||
|
{
|
||||||
|
if old_task.get_state() != TaskState::Finished
|
||||||
|
{
|
||||||
|
self.queue_task(old_task);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None =>
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sleep the thread so that other threads
|
||||||
|
// get a chance to run
|
||||||
|
::std::thread::sleep(Duration::new(0, 100));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -74,19 +74,19 @@ impl Spawner
|
|||||||
!self.sibling_tasks.is_empty()
|
!self.sibling_tasks.is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get an Iterator over the spawned child tasks.
|
/// Get a Vector of the spawned child tasks.
|
||||||
///
|
///
|
||||||
/// This will remove all the tasks from this spawner.
|
/// This will remove all the tasks from this spawner.
|
||||||
pub fn drain_child_tasks(&mut self) -> Drain<Box<TaskStateMachine>>
|
pub fn retrieve_child_tasks(&mut self) -> Vec<Box<TaskStateMachine>>
|
||||||
{
|
{
|
||||||
self.child_tasks.drain(..)
|
self.child_tasks.drain(..).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get an Iterator over the spawned sibling tasks.
|
/// Get a Vector of the spawned sibling tasks.
|
||||||
///
|
///
|
||||||
/// This will remove all the tasks from this spawner.
|
/// This will remove all the tasks from this spawner.
|
||||||
pub fn drain_sibling_tasks(&mut self) -> Drain<Box<TaskStateMachine>>
|
pub fn retrieve_sibling_tasks(&mut self) -> Vec<Box<TaskStateMachine>>
|
||||||
{
|
{
|
||||||
self.sibling_tasks.drain(..)
|
self.sibling_tasks.drain(..).collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user