#![allow(dead_code)]
use std::collections::VecDeque;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Mutex};
use std::thread;
use std::thread::JoinHandle;
mod test;
#[derive(Debug)]
struct BackgroundWorker<Input: 'static, Output: 'static>
where
Input: std::marker::Send,
Output: std::marker::Send + std::clone::Clone + std::cmp::PartialEq,
{
function: fn(Input) -> Output,
thread_handle: Option<JoinHandle<()>>,
pub outqueue: Arc<Mutex<VecDeque<Output>>>,
pub inqueue: Arc<Mutex<VecDeque<Input>>>,
thread_dead: Arc<AtomicBool>,
}
impl<Input: 'static, Output: 'static> BackgroundWorker<Input, Output>
where
Input: std::marker::Send,
Output: std::marker::Send + std::clone::Clone + std::cmp::PartialEq,
{
pub fn new(func: fn(Input) -> Output) -> BackgroundWorker<Input, Output> {
BackgroundWorker {
function: func,
outqueue: Arc::new(Mutex::new(VecDeque::new())),
inqueue: Arc::new(Mutex::new(VecDeque::new())),
thread_handle: None,
thread_dead: Arc::new(AtomicBool::new(true)),
}
}
pub fn pop(&mut self) -> Option<Output> {
self.outqueue.lock().unwrap().pop_front()
}
pub fn pop_vec(&mut self, buffer: &mut Vec<Output>) -> usize{
let mut num_successful = 0;
for i in 0..buffer.len(){
if let Some(data) = self.pop(){
buffer[i] = data;
num_successful += 1;
}
}
num_successful
}
fn create_thread(&mut self) {
let inqueue_clone = self.inqueue.clone();
let outqueue_clone = self.outqueue.clone();
let thread_dead_clone = self.thread_dead.clone();
let func_clone = self.function.clone();
self.thread_dead.store(false, Ordering::Release);
self.thread_handle = Some(thread::spawn(move || {
while let Some(data) = inqueue_clone.lock().unwrap().pop_front() {
outqueue_clone.lock().unwrap().push_back(func_clone(data));
}
thread_dead_clone.store(true, Ordering::Release);
}));
}
fn spawn_thread_if_dead(&mut self) {
if self.thread_dead.load(Ordering::Acquire) {
self.create_thread();
}
}
pub fn enque(&mut self, value: Input) {
self.inqueue.lock().unwrap().push_back(value);
self.spawn_thread_if_dead();
}
pub fn enque_vec(&mut self, values: Vec<Input>) {
for i in values {
self.inqueue.lock().unwrap().push_back(i);
}
self.spawn_thread_if_dead();
}
pub fn join(&mut self) {
if !self.thread_dead.load(Ordering::Acquire) {
let mut x = None;
std::mem::swap(&mut x, &mut self.thread_handle);
if let Some(y) = x {
y.join().unwrap();
}
}
}
}