use super::{Name, Thread};
use crate::{FrameworkError, FrameworkErrorKind::ThreadError, Map};
use std::{convert::TryInto, sync};
pub type Reader<'a> = sync::RwLockReadGuard<'a, Manager>;
pub type Writer<'a> = sync::RwLockWriteGuard<'a, Manager>;
#[derive(Debug, Default)]
pub struct Manager {
threads: Map<Name, Thread>,
}
impl Manager {
pub fn spawn<F>(&mut self, name: impl TryInto<Name>, f: F) -> Result<(), FrameworkError>
where
F: FnOnce() + Send + 'static,
{
let name = name
.try_into()
.ok()
.ok_or_else(|| format_err!(ThreadError, "invalid thread name"))?;
if self.threads.contains_key(&name) {
fail!(ThreadError, "duplicate name: {}", name);
}
let thread = Thread::spawn(name.clone(), f)?;
self.threads.insert(name, thread);
Ok(())
}
pub fn join(&mut self) -> Result<(), FrameworkError> {
let mut names = Vec::with_capacity(self.threads.len());
for (name, thread) in self.threads.iter() {
names.push(name.clone());
thread.request_termination();
}
for name in names.into_iter() {
if let Some(thread) = self.threads.remove(&name) {
thread.join()?;
}
}
Ok(())
}
}