|
- use std::cell::UnsafeCell;
-
- use hibitset::BitSetLike;
- use parallel_iterator::{Consumer, Executor, Folder, ParallelIterator, Producer};
-
- use crate::misc::{BitIter, BitProducer, TokioExecutor};
-
- use super::Join;
-
- pub trait ParJoin: Join {
- fn par_join(self) -> JoinParIter<Self>
- where
- Self: Sized,
- {
- if <Self as Join>::is_unconstrained() {
- log::warn!(
- "`ParJoin` possibly iterating through all indices, you might've made a join with all `MaybeJoin`s, which is unbounded in length."
- );
- }
-
- JoinParIter(self)
- }
- }
-
- pub struct JoinParIter<J>(J);
-
- impl<J> ParallelIterator for JoinParIter<J>
- where
- J: Join + Send,
- J::Type: Send,
- J::Mask: Send + Sync,
- J::Value: Send,
- {
- type Item = J::Type;
-
- fn drive<C>(self, consumer: C) -> C::Result
- where
- C: Consumer<Self::Item>,
- {
- let (keys, values) = self.0.open();
- let values = UnsafeCell::new(values);
-
- let keys = BitIter::new(&keys, [0, 0, 0, keys.layer3()], [0; 3]);
-
- let producer = BitProducer::new(keys, 3);
- let producer = JoinProducer::<J>::new(producer, &values);
-
- TokioExecutor.exec(producer, consumer)
- }
- }
-
- struct JoinProducer<'a, J>
- where
- J: Join + Send,
- J::Type: Send,
- J::Mask: Send,
- J::Value: Send,
- {
- pub(crate) keys: BitProducer<'a, J::Mask>,
- pub(crate) values: &'a UnsafeCell<J::Value>,
- }
-
- impl<'a, J> JoinProducer<'a, J>
- where
- J: Join + Send,
- J::Type: Send,
- J::Mask: Send,
- J::Value: Send,
- {
- fn new(keys: BitProducer<'a, J::Mask>, values: &'a UnsafeCell<J::Value>) -> Self {
- JoinProducer { keys, values }
- }
- }
-
- unsafe impl<'a, J> Send for JoinProducer<'a, J>
- where
- J: Join + Send,
- J::Type: Send,
- J::Value: Send + 'a,
- J::Mask: Send + Sync + 'a,
- {
- }
-
- impl<'a, J> Producer for JoinProducer<'a, J>
- where
- J: Join + Send,
- J::Type: Send,
- J::Value: Send + 'a,
- J::Mask: Send + Sync + 'a,
- {
- type Item = J::Type;
-
- fn split(self) -> (Self, Option<Self>) {
- let (cur, other) = self.keys.split();
- let values = self.values;
- let first = JoinProducer::new(cur, values);
- let second = other.map(|o| JoinProducer::new(o, values));
-
- (first, second)
- }
-
- fn fold_with<F>(self, folder: F) -> F
- where
- F: Folder<Self::Item>,
- {
- let JoinProducer { values, keys, .. } = self;
- let iter = keys
- .iter
- .map(|idx| unsafe { J::get(&mut *values.get(), idx) });
-
- folder.consume_iter(iter)
- }
- }
|