#![allow(dead_code)]
use binary_heap_plus::{BinaryHeap};
use std::sync::atomic::{AtomicBool, AtomicU8, Ordering};
use std::sync::*;
use crate::branch::Branch;
use crate::{IBranchFilter, UserDualStore};
use compare::Compare;
pub struct BlockingQueue<T, C, DualStore>
where
T: IBranchFilter,
DualStore : UserDualStore,
C : Compare<Branch<T,DualStore>> + Clone
{
queue: Mutex<BinaryHeap<Branch<T,DualStore>, C>>,
did_swap_priority: AtomicBool,
flushing : AtomicBool,
in_progress: AtomicU8,
condvar: Condvar,
compare_bound : C,
compare_without_bound : C
}
impl<T: IBranchFilter, C : Compare<Branch<T,DualStore >> + Clone, DualStore : UserDualStore> BlockingQueue<T , C, DualStore>
{
pub fn new(compare_bound : C, compare_without_bound : C) -> Self {
let heap = BinaryHeap::from_vec_cmp(vec![] as Vec<Branch<T, DualStore>>, compare_without_bound.clone());
Self {
queue: Mutex::new(heap),
in_progress: AtomicU8::new(0),
condvar: Condvar::new(),
did_swap_priority: AtomicBool::new(false),
compare_bound,
compare_without_bound,
flushing : false.into()
}
}
pub fn now_has_bound(&self) {
if !self.did_swap_priority.load(self::Ordering::Relaxed) {
self.did_swap_priority.store(true, self::Ordering::SeqCst);
let mut lq = self.queue.lock().unwrap();
lq.replace_cmp(self.compare_bound.clone());
}
}
pub fn add_job(&self, t: Branch<T, DualStore>) {
if self.flushing.load(Ordering::SeqCst) { return;}
let mut lq = self.queue.lock().unwrap();
lq.push(t);
self.condvar.notify_one();
}
pub fn get_job(&self) -> Option<Branch<T, DualStore>> {
let mut lq = self.queue.lock().unwrap();
while lq.len() == 0 && self.in_progress.load(Ordering::SeqCst) > 0 && !self.flushing.load(Ordering::SeqCst) {
lq = self.condvar.wait(lq).unwrap();
}
if self.flushing.load(Ordering::SeqCst) { return None}
let job = lq.pop();
if job.is_some() {
self.in_progress.fetch_add(1, Ordering::SeqCst);
}
job
}
pub fn job_done(&self) {
self.in_progress.fetch_sub(1, Ordering::SeqCst);
self.condvar.notify_all();
}
pub fn flush_and_terminate(&self) {
self.flushing.store(true, Ordering::SeqCst);
self.in_progress.store(0, Ordering::SeqCst);
self.condvar.notify_all();
}
pub fn copy_of_queue(&self) -> Vec<Branch<T, DualStore>> {
self.queue.lock().unwrap().clone().into_vec()
}
pub fn lowest_bound(&self) -> Option<f64> {
self.queue.lock().unwrap().iter().map(|i| i.old_obj_bound).min_by(|a, b| a.partial_cmp(b).unwrap())
}
pub fn len(&self) -> usize {
self.queue.lock().unwrap().len()
}
}