mod iterator_consumer;
pub mod scope;
use std::{
cell::UnsafeCell,
future::Future,
iter::ExactSizeIterator,
mem::{ManuallyDrop, MaybeUninit},
};
pub use iterator_consumer::{FutureConsumer, RayonConsumer, TryFutureConsumer};
pub use scope::scope;
pub async unsafe fn par_iter_then_collect<I, F, O>(iter: I) -> Vec<O>
where
I: IntoIterator<Item = F>,
I::IntoIter: ExactSizeIterator,
F: Future<Output = O> + Send + Sync,
O: Send + Sync,
{
#[repr(transparent)]
struct SyncUnsafeCell<T: ?Sized>(UnsafeCell<T>);
unsafe impl<T: ?Sized + Sync> Sync for SyncUnsafeCell<T> {}
let iter = iter.into_iter();
let output: Box<[MaybeUninit<SyncUnsafeCell<O>>]> = Box::new_uninit_slice(iter.len());
scope(|token| {
for (i, f) in iter.enumerate() {
let spawner = unsafe { token.used((f, &output)) };
spawner.spawn(move |(f, output)| async move {
let result = f.await;
let slot = &output[i];
let slot = slot.as_ptr().cast::<UnsafeCell<O>>();
unsafe {
UnsafeCell::raw_get(slot).write(result);
}
});
}
})
.await;
let output = unsafe { output.assume_init() };
let output = Vec::from(output);
unsafe {
let mut output = ManuallyDrop::new(output);
let ptr = output.as_mut_ptr();
let len = output.len();
let cap = output.capacity();
let ptr = ptr.cast::<O>();
Vec::from_raw_parts(ptr, len, cap)
}
}