2016-03-25 02:45:34 -04:00
|
|
|
use std::collections::binary_heap::BinaryHeap;
|
|
|
|
use std::ops::{Deref, DerefMut};
|
|
|
|
use std::sync::{Arc, Mutex};
|
|
|
|
use std::sync::mpsc::{channel, Receiver, Sender, TryRecvError};
|
|
|
|
use std::thread::JoinHandle;
|
|
|
|
use std::time::Duration;
|
|
|
|
use std::vec::Vec;
|
|
|
|
|
|
|
|
use ::task::Task;
|
|
|
|
use ::task_state::TaskState;
|
|
|
|
use ::thread_data::ThreadData;
|
|
|
|
use ::thread_state::ThreadState;
|
|
|
|
|
|
|
|
use chrono::MonotonicTime;
|
|
|
|
|
|
|
|
|
|
|
|
|
2016-03-18 16:17:01 -04:00
|
|
|
///
|
|
|
|
pub struct Thread
|
|
|
|
{
|
|
|
|
///
|
2016-03-25 02:45:34 -04:00
|
|
|
state: ThreadState,
|
|
|
|
|
|
|
|
///
|
|
|
|
current_task: Option<Task>,
|
|
|
|
|
|
|
|
///
|
|
|
|
task_queue: Arc<Mutex<BinaryHeap<Task>>>,
|
|
|
|
|
|
|
|
///
|
|
|
|
shutdown_receiver: Receiver<bool>,
|
|
|
|
|
|
|
|
///
|
|
|
|
state_sender: Sender<ThreadState>
|
2016-03-18 16:17:01 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl Thread
|
|
|
|
{
|
2016-03-25 02:45:34 -04:00
|
|
|
///
|
|
|
|
pub fn new(queue: Arc<Mutex<BinaryHeap<Task>>>,
|
|
|
|
shutdown_r: Receiver<bool>,
|
|
|
|
state_s: Sender<ThreadState>)
|
|
|
|
-> Thread
|
2016-03-18 16:17:01 -04:00
|
|
|
{
|
|
|
|
Thread
|
|
|
|
{
|
2016-03-25 02:45:34 -04:00
|
|
|
state: ThreadState::Starting,
|
|
|
|
current_task: None,
|
|
|
|
task_queue: queue,
|
|
|
|
shutdown_receiver: shutdown_r,
|
|
|
|
state_sender: state_s
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
///
|
|
|
|
pub fn process(&mut self)
|
|
|
|
{
|
|
|
|
let mut task_completed: bool;
|
|
|
|
|
|
|
|
// 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) =>
|
|
|
|
{
|
|
|
|
// Process the task this thread is
|
|
|
|
// currently working on.
|
|
|
|
task.process();
|
|
|
|
|
|
|
|
match task.state
|
|
|
|
{
|
|
|
|
TaskState::Finished =>
|
|
|
|
{
|
|
|
|
task_completed = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
_ =>
|
|
|
|
{
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
None =>
|
|
|
|
{
|
|
|
|
// This thread does not have a current task.
|
|
|
|
// Get another task to work on from the Queue.
|
|
|
|
match self.task_queue.lock()
|
|
|
|
{
|
|
|
|
Ok(ref mut guard) =>
|
|
|
|
{
|
|
|
|
self.current_task = guard.deref_mut().pop();
|
|
|
|
|
|
|
|
match self.current_task
|
|
|
|
{
|
|
|
|
Some(_) =>
|
|
|
|
{
|
|
|
|
debug!("Received a task.");
|
|
|
|
}
|
|
|
|
|
|
|
|
None =>
|
|
|
|
{
|
|
|
|
debug!("No new task to process.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Err(error) =>
|
|
|
|
{
|
|
|
|
error!("{}", error);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we don't have a task to process,
|
|
|
|
// then we may need to switch over to
|
|
|
|
// an idle state.
|
|
|
|
match self.current_task
|
|
|
|
{
|
|
|
|
Some(_) =>
|
|
|
|
{
|
|
|
|
self.change_state(ThreadState::Processing);
|
|
|
|
}
|
|
|
|
|
|
|
|
None =>
|
|
|
|
{
|
|
|
|
match self.state
|
|
|
|
{
|
|
|
|
ThreadState::Idle =>
|
|
|
|
{
|
|
|
|
// The thread is already sitting idle.
|
|
|
|
}
|
|
|
|
|
|
|
|
_ =>
|
|
|
|
{
|
|
|
|
// There is nothing for this thread
|
|
|
|
// to process, so mark the thread as idle.
|
|
|
|
self.change_state(ThreadState::Idle);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if task_completed == true
|
|
|
|
{
|
|
|
|
println!("Task completed.");
|
|
|
|
self.current_task = None;
|
|
|
|
self.change_state(ThreadState::Idle);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
///
|
|
|
|
fn change_state(&mut self, new_state: ThreadState)
|
|
|
|
{
|
|
|
|
self.state = new_state;
|
|
|
|
match self.state_sender.send(self.state)
|
|
|
|
{
|
|
|
|
Ok(_) =>
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
Err(error) =>
|
|
|
|
{
|
|
|
|
// We lost our connection to the
|
|
|
|
// state channel.
|
|
|
|
warn!("{}", error);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Queues a task to be processed.
|
|
|
|
fn queue_task(&mut self, task: Task)
|
|
|
|
{
|
|
|
|
// Just add the task to the queue.
|
|
|
|
match self.task_queue.lock()
|
|
|
|
{
|
|
|
|
Ok(ref mut guard) =>
|
|
|
|
{
|
|
|
|
guard.deref_mut().push(task);
|
|
|
|
}
|
|
|
|
|
|
|
|
Err(error) =>
|
|
|
|
{
|
|
|
|
error!("{}", error);
|
|
|
|
}
|
2016-03-18 16:17:01 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|