use crate::{Dominate, ParetoFront};
use thread_local::ThreadLocal;
use std::{cell::UnsafeCell, marker::Send};
#[derive(Default, Debug)]
pub struct ConcurrentParetoFront<T: Dominate + Send>
{
inner_front: ThreadLocal<UnsafeCell<ParetoFront<T>>>
}
impl<T: Dominate + Send> ConcurrentParetoFront<T>
{
pub fn new() -> Self
{
ConcurrentParetoFront { inner_front: ThreadLocal::new() }
}
pub fn push(&self, new_element: T) -> bool
{
let front_ptr = self.inner_front.get_or_default().get();
let front = unsafe { &mut *front_ptr };
front.push(new_element)
}
pub fn into_sequential(self) -> ParetoFront<T>
{
self.inner_front
.into_iter()
.map(|r| r.into_inner()) .reduce(|mut front_acc, front| {
front_acc.merge(front);
front_acc
})
.unwrap_or_default() }
}
impl<T: Dominate + Send> From<ConcurrentParetoFront<T>> for Vec<T>
{
fn from(front: ConcurrentParetoFront<T>) -> Vec<T>
{
front.into_sequential().into()
}
}
impl<T: Dominate + Send> From<ConcurrentParetoFront<T>> for ParetoFront<T>
{
fn from(front: ConcurrentParetoFront<T>) -> ParetoFront<T>
{
front.into_sequential()
}
}
impl<T: Dominate + Send> From<ParetoFront<T>> for ConcurrentParetoFront<T>
{
fn from(front: ParetoFront<T>) -> Self
{
let result = ConcurrentParetoFront::new();
result.inner_front.get_or(|| UnsafeCell::new(front));
result
}
}
impl<T: Dominate + Send> IntoIterator for ConcurrentParetoFront<T>
{
type Item = T;
type IntoIter = std::vec::IntoIter<T>;
fn into_iter(self) -> Self::IntoIter
{
self.into_sequential().into_iter()
}
}
impl<T: Dominate + Send> FromIterator<T> for ConcurrentParetoFront<T>
{
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self
{
let mut front = ConcurrentParetoFront::new();
front.extend(iter); front
}
}
impl<T: Dominate + Send> Extend<T> for ConcurrentParetoFront<T>
{
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I)
{
let front_ptr = self.inner_front.get_or_default().get();
let front = unsafe { &mut *front_ptr };
front.extend(iter)
}
}