apprentice/src/thread.rs

194 lines
4.1 KiB
Rust
Raw Normal View History

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
{
///
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
{
///
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
{
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
}
}
}