par_bench/
run_meta.rs

1use std::num::NonZero;
2
3/// Informs a benchmark run callback about the basic metadata associated with the run.
4///
5/// This type is passed to various callback functions during benchmark execution,
6/// providing information about the current thread group, total number of groups,
7/// and iteration count. This allows callbacks to behave differently based on
8/// their context within the benchmark run.
9///
10/// # Examples
11///
12/// ```
13/// use many_cpus::ProcessorSet;
14/// use par_bench::{Run, ThreadPool};
15/// use new_zealand::nz;
16///
17/// # fn main() {
18/// # if let Some(processors) = ProcessorSet::builder().take(nz!(4)) {
19/// let mut pool = ThreadPool::new(&processors);
20///
21/// let run = Run::new()
22///     .groups(nz!(2)) // 2 groups of 2 threads each
23///     .prepare_thread(|args| {
24///         println!("Thread in group {} of {}",
25///                  args.meta().group_index(),
26///                  args.meta().group_count());
27///         println!("Will execute {} iterations", args.meta().iterations());
28///         
29///         // Return different state based on group
30///         if args.meta().group_index() == 0 {
31///             "reader_thread"
32///         } else {
33///             "writer_thread"
34///         }
35///     })
36///     .prepare_iter(|args| *args.thread_state())
37///     .iter(|mut args| {
38///         let thread_type = args.take_iter_state();
39///         match thread_type {
40///             "reader_thread" => { /* reader work */ },
41///             "writer_thread" => { /* writer work */ },
42///             _ => unreachable!(),
43///         }
44///     });
45///
46/// let _results = run.execute_on(&mut pool, 100);
47/// # }
48/// # }
49#[derive(Clone, Copy, Debug, Eq, PartialEq)]
50pub struct RunMeta {
51    /// The index of the current thread group, starting from 0.
52    group_index: usize,
53
54    /// The total number of thread groups in the run.
55    group_count: NonZero<usize>,
56
57    /// The total number of threads used to execute the run.
58    thread_count: NonZero<usize>,
59
60    /// How many iterations will be executed as part of this run.
61    iterations: u64,
62}
63
64impl RunMeta {
65    /// Creates a new `RunMeta` with the specified index and total count.
66    pub(crate) fn new(
67        group_index: usize,
68        group_count: NonZero<usize>,
69        thread_count: NonZero<usize>,
70        iterations: u64,
71    ) -> Self {
72        Self {
73            group_index,
74            group_count,
75            thread_count,
76            iterations,
77        }
78    }
79
80    /// The index of the current thread group, starting from 0.
81    #[must_use]
82    pub fn group_index(&self) -> usize {
83        self.group_index
84    }
85
86    /// The total number of thread groups in the run.
87    #[must_use]
88    #[cfg_attr(test, mutants::skip)] // cargo-mutants does not understand NonZero - unviable.
89    pub fn group_count(&self) -> NonZero<usize> {
90        self.group_count
91    }
92
93    /// The total number of threads used to execute the run.
94    #[must_use]
95    #[cfg_attr(test, mutants::skip)] // cargo-mutants does not understand NonZero - unviable.
96    pub fn thread_count(&self) -> NonZero<usize> {
97        self.thread_count
98    }
99
100    /// How many iterations will be executed as part of this run.
101    #[must_use]
102    pub fn iterations(&self) -> u64 {
103        self.iterations
104    }
105}