1use crate::queue::Queue;
2use crate::task_batch::TaskBatch;
3use std::marker::PhantomData;
4use std::sync::atomic::{AtomicUsize, Ordering};
5use std::thread::{self, Thread};
6
7pub struct Scope<'scope, 'env: 'scope> {
11 counter: AtomicUsize,
12 queue: &'env Queue,
13 thread: Thread,
14 _marker: PhantomData<(&'scope mut &'scope (), &'env mut &'env ())>,
15}
16
17impl<'scope, 'env> Scope<'scope, 'env> {
18 pub(crate) fn new(queue: &'env Queue) -> Self {
19 Self {
20 counter: AtomicUsize::new(0),
21 queue,
22 thread: thread::current(),
23 _marker: PhantomData,
24 }
25 }
26
27 #[inline]
29 pub fn run<T: 'scope>(&self, task_fn: fn(&T), params: &'scope [T]) {
30 if !params.is_empty() {
31 self.counter.fetch_add(params.len(), Ordering::Relaxed);
32 let batch = unsafe {
33 TaskBatch::new(
34 task_fn,
35 params,
36 Some((&raw const self.counter, self.thread.clone())),
37 )
38 };
39 self.queue.enqueue(batch, params.len());
40 }
41 }
42
43 #[inline]
47 pub fn wait(&self) {
48 while self.counter.load(Ordering::Acquire) != 0 {
49 thread::park();
50 }
51 }
52
53 #[must_use]
55 #[inline]
56 pub fn is_complete(&self) -> bool {
57 self.counter.load(Ordering::Acquire) == 0
58 }
59}
60
61pub(crate) struct ScopeGuard<'s, 'scope, 'env>(pub &'s Scope<'scope, 'env>);
63
64impl Drop for ScopeGuard<'_, '_, '_> {
65 fn drop(&mut self) {
66 self.0.wait();
67 }
68}