use prelude::v1::*;
use base::*;
use task::*;
use mutex::*;
use queue::*;
use units::*;
pub trait ComputeTaskBuilder {
fn compute<F, R>(&self, func: F) -> Result<ComputeTask<R>, FreeRtosError>
where F: FnOnce() -> R,
F: Send + 'static,
R: Sync + Send + 'static;
}
impl ComputeTaskBuilder for TaskBuilder {
#[cfg(target_os="none")]
fn compute<F, R>(&self, func: F) -> Result<ComputeTask<R>, FreeRtosError>
where F: FnOnce() -> R,
F: Send + 'static,
R: Sync + Send + 'static
{
let (task, result, status) = {
let result = Arc::new(try!(Mutex::new(None)));
let status = Arc::new(try!(Queue::new(1)));
let task_result = result.clone();
let task_status = status.clone();
let task = try!(self.start(move || {
{
let mut lock = task_result.lock(Duration::Infinite).unwrap();
let r = func();
*lock = Some(r);
}
drop(task_result);
task_status.send(ComputeTaskStatus::Finished, Duration::Infinite).unwrap();
}));
(task, result, status)
};
Ok(ComputeTask {
task: task,
result: result,
status: status,
finished: false,
})
}
#[cfg(not(target_os="none"))]
fn compute<F, R>(&self, func: F) -> Result<ComputeTask<R>, FreeRtosError>
where F: FnOnce() -> R,
F: Send + 'static,
R: Sync + Send + 'static
{
let r = func();
Ok(ComputeTask {
task: Task::new().start(|| {}).unwrap(),
result: Arc::new(Mutex::new(Some(r)).unwrap()),
status: Arc::new(Queue::new(1).unwrap()),
finished: false,
})
}
}
pub struct ComputeTask<R> {
task: Task,
result: Arc<Mutex<Option<R>>>,
status: Arc<Queue<ComputeTaskStatus>>,
finished: bool,
}
#[derive(Debug, Copy, Clone)]
enum ComputeTaskStatus {
Finished,
}
use core::fmt::Debug;
impl<R: Debug> ComputeTask<R> {
pub fn get_task(&self) -> &Task {
&self.task
}
pub fn wait_for_result(&mut self, max_wait: Duration) -> Result<(), FreeRtosError> {
if self.finished == true {
Ok(())
} else {
match self.status.receive(max_wait) {
Ok(ComputeTaskStatus::Finished) => {
self.finished = true;
Ok(())
}
Err(e) => Err(e),
}
}
}
pub fn into_result(mut self, max_wait: Duration) -> Result<R, FreeRtosError> {
try!(self.wait_for_result(max_wait));
if self.finished != true {
panic!("ComputeTask should be finished!");
}
let m = Arc::try_unwrap(self.result)
.expect("ComputeTask: Arc should have only one reference left!");
let option_r = m.into_inner();
let r = option_r.expect("ComputeTask: Result should be a Some(R)!");
Ok(r)
}
}