pub trait Strategy:
Clone
+ Send
+ Sync
+ Debug
+ 'static {
Show 14 methods
// Required methods
fn manual(&self) -> Manual<Self>
where Self: Sized;
fn spawn<F, T>(&self, f: F) -> impl Future<Output = T> + Send + 'static
where F: FnOnce(Self) -> T + Send + 'static,
T: Send + 'static;
fn run<R, SEQ, PAR>(&self, len: usize, serial: SEQ, parallel: PAR) -> R
where R: Send,
SEQ: FnOnce() -> R + Send,
PAR: FnOnce() -> R + Send;
fn try_run<R, E, SEQ, PAR>(
&self,
len: usize,
serial: SEQ,
parallel: PAR,
) -> Result<R, E>
where R: Send,
E: Send,
SEQ: FnOnce() -> Result<R, E> + Send,
PAR: FnOnce() -> Result<R, E> + Send;
fn fold_init<I, INIT, T, R, ID, F, RD>(
&self,
iter: I,
init: INIT,
identity: ID,
fold_op: F,
reduce_op: RD,
) -> R
where I: IntoIterator<IntoIter: Send, Item: Send> + Send,
INIT: Fn() -> T + Send + Sync,
T: Send,
R: Send,
ID: Fn() -> R + Send + Sync,
F: Fn(R, &mut T, I::Item) -> R + Send + Sync,
RD: Fn(R, R) -> R + Send + Sync;
fn try_fold<I, R, E, ID, F, RD>(
&self,
iter: I,
identity: ID,
fold_op: F,
reduce_op: RD,
) -> Result<R, E>
where I: IntoIterator<IntoIter: Send, Item: Send> + Send,
R: Send,
E: Send,
ID: Fn() -> R + Send + Sync,
F: Fn(R, I::Item) -> Result<R, E> + Send + Sync,
RD: Fn(R, R) -> R + Send + Sync;
fn join<A, B, RA, RB>(&self, a: A, b: B) -> (RA, RB)
where A: FnOnce() -> RA + Send,
B: FnOnce() -> RB + Send,
RA: Send,
RB: Send;
fn sort_by<T, C>(&self, items: &mut [T], compare: C)
where T: Send,
C: Fn(&T, &T) -> Ordering + Send + Sync;
// Provided methods
fn fold<I, R, ID, F, RD>(
&self,
iter: I,
identity: ID,
fold_op: F,
reduce_op: RD,
) -> R
where I: IntoIterator<IntoIter: Send, Item: Send> + Send,
R: Send,
ID: Fn() -> R + Send + Sync,
F: Fn(R, I::Item) -> R + Send + Sync,
RD: Fn(R, R) -> R + Send + Sync { ... }
fn map_collect_vec<I, F, T>(&self, iter: I, map_op: F) -> Vec<T>
where I: IntoIterator<IntoIter: Send, Item: Send> + Send,
F: Fn(I::Item) -> T + Send + Sync,
T: Send { ... }
fn try_map_collect_vec<I, F, T, E>(
&self,
iter: I,
map_op: F,
) -> Result<Vec<T>, E>
where I: IntoIterator<IntoIter: Send, Item: Send> + Send,
F: Fn(I::Item) -> Result<T, E> + Send + Sync,
T: Send,
E: Send { ... }
fn map_init_collect_vec<I, INIT, T, F, R>(
&self,
iter: I,
init: INIT,
map_op: F,
) -> Vec<R>
where I: IntoIterator<IntoIter: Send, Item: Send> + Send,
INIT: Fn() -> T + Send + Sync,
T: Send,
F: Fn(&mut T, I::Item) -> R + Send + Sync,
R: Send { ... }
fn map_init_collect_vec_with_multiplier<I, INIT, T, F, R>(
&self,
iter: I,
_multiplier: usize,
init: INIT,
map_op: F,
) -> Vec<R>
where I: IntoIterator<IntoIter: Send, Item: Send> + Send,
INIT: Fn() -> T + Send + Sync,
T: Send,
F: Fn(&mut T, I::Item) -> R + Send + Sync,
R: Send { ... }
fn map_partition_collect_vec<I, F, K, U>(
&self,
iter: I,
map_op: F,
) -> (Vec<U>, Vec<K>)
where I: IntoIterator<IntoIter: Send, Item: Send> + Send,
F: Fn(I::Item) -> (K, Option<U>) + Send + Sync,
K: Send,
U: Send { ... }
}Expand description
A strategy for executing fold operations.
This trait abstracts over sequential and parallel execution, allowing algorithms to be written generically and then executed with different strategies depending on the use case (e.g., sequential for testing/debugging, parallel for production).
Required Methods§
Sourcefn manual(&self) -> Manual<Self>where
Self: Sized,
fn manual(&self) -> Manual<Self>where
Self: Sized,
Returns a strategy wrapper for manually partitioned work.
Sourcefn spawn<F, T>(&self, f: F) -> impl Future<Output = T> + Send + 'static
fn spawn<F, T>(&self, f: F) -> impl Future<Output = T> + Send + 'static
Submit one CPU-bound job to this strategy.
The returned future resolves when the submitted job completes, but blocking on external synchronization or I/O inside the job can occupy execution capacity until it returns. When the polling thread itself belongs to the strategy’s execution resources (e.g. a runtime whose executor thread is registered as a pool worker), the job (and other pending work) may be executed inline on that thread rather than waited on.
If the job panics, the panic is propagated to the caller; it never aborts the process.
Sourcefn run<R, SEQ, PAR>(&self, len: usize, serial: SEQ, parallel: PAR) -> R
fn run<R, SEQ, PAR>(&self, len: usize, serial: SEQ, parallel: PAR) -> R
Runs either a serial or parallel body.
Sourcefn try_run<R, E, SEQ, PAR>(
&self,
len: usize,
serial: SEQ,
parallel: PAR,
) -> Result<R, E>
fn try_run<R, E, SEQ, PAR>( &self, len: usize, serial: SEQ, parallel: PAR, ) -> Result<R, E>
Like run, but for fallible work.
The strategy chooses and runs either the serial or parallel body, returning the first error produced by the chosen body. Elapsed time is only recorded on success, so abort-early error paths cannot poison the adaptive policy’s estimates.
Sourcefn fold_init<I, INIT, T, R, ID, F, RD>(
&self,
iter: I,
init: INIT,
identity: ID,
fold_op: F,
reduce_op: RD,
) -> R
fn fold_init<I, INIT, T, R, ID, F, RD>( &self, iter: I, init: INIT, identity: ID, fold_op: F, reduce_op: RD, ) -> R
Reduces a collection to a single value with per-partition initialization.
Similar to fold, but provides a separate initialization value
that is created once per partition. This is useful when the fold operation
requires mutable state that should not be shared across partitions (e.g., a
scratch buffer, RNG, or expensive-to-clone resource).
§Arguments
iter: The collection to fold overinit: Creates the per-partition initialization valueidentity: Creates the identity value for the accumulatorfold_op: Combines accumulator with init state and item:(acc, &mut init, item) -> accreduce_op: Combines two accumulators:(acc1, acc2) -> acc
§Examples
use commonware_parallel::{Strategy, Sequential};
let strategy = Sequential;
let data = vec![1u32, 2, 3, 4, 5];
// Use a scratch buffer to avoid allocations in the inner loop
let result: Vec<String> = strategy.fold_init(
&data,
|| String::with_capacity(16), // Per-partition scratch buffer
Vec::new, // Identity for accumulator
|mut acc, buf, &n| {
buf.clear();
use std::fmt::Write;
write!(buf, "num:{}", n).unwrap();
acc.push(buf.clone());
acc
},
|mut a, b| { a.extend(b); a },
);
assert_eq!(result, vec!["num:1", "num:2", "num:3", "num:4", "num:5"]);Sourcefn try_fold<I, R, E, ID, F, RD>(
&self,
iter: I,
identity: ID,
fold_op: F,
reduce_op: RD,
) -> Result<R, E>
fn try_fold<I, R, E, ID, F, RD>( &self, iter: I, identity: ID, fold_op: F, reduce_op: RD, ) -> Result<R, E>
Reduces a collection to a single value using a fallible fold operation.
Similar to fold, but fold_op may fail. Implementations may stop
applying fold_op after an error is observed. When more than one partition fails,
any error may be returned.
Adaptive strategies must only record elapsed time when the fold succeeds, so abort-early error paths cannot poison the policy’s estimates.
§Arguments
iter: The collection to fold overidentity: A closure that produces the identity value for the fold.fold_op: Fallibly combines an accumulator with a single item:(acc, item) -> Result<acc, E>reduce_op: Combines two successful accumulators:(acc1, acc2) -> acc.
Sourcefn join<A, B, RA, RB>(&self, a: A, b: B) -> (RA, RB)
fn join<A, B, RA, RB>(&self, a: A, b: B) -> (RA, RB)
Executes two closures, potentially in parallel, and returns both results.
For Sequential, this executes a then b on the current thread.
For Rayon, this executes a and b using rayon::join.
§Arguments
a: First closure to executeb: Second closure to execute
§Examples
use commonware_parallel::{Strategy, Sequential};
let strategy = Sequential;
let (sum, product) = strategy.join(
|| (1..=5).sum::<i32>(),
|| (1..=5).product::<i32>(),
);
assert_eq!(sum, 15);
assert_eq!(product, 120);Sourcefn sort_by<T, C>(&self, items: &mut [T], compare: C)
fn sort_by<T, C>(&self, items: &mut [T], compare: C)
Sorts a slice with a comparator, preserving the order of equal elements.
§Examples
use commonware_parallel::{Strategy, Sequential};
let strategy = Sequential;
let mut data = vec![3, 1, 2];
strategy.sort_by(&mut data, |a, b| a.cmp(b));
assert_eq!(data, vec![1, 2, 3]);Provided Methods§
Sourcefn fold<I, R, ID, F, RD>(
&self,
iter: I,
identity: ID,
fold_op: F,
reduce_op: RD,
) -> R
fn fold<I, R, ID, F, RD>( &self, iter: I, identity: ID, fold_op: F, reduce_op: RD, ) -> R
Reduces a collection to a single value using fold and reduce operations.
This method processes elements from the iterator, combining them into a single result.
§Arguments
iter: The collection to fold overidentity: A closure that produces the identity value for the fold.fold_op: Combines an accumulator with a single item:(acc, item) -> accreduce_op: Combines two accumulators:(acc1, acc2) -> acc.
§Examples
§Sum of Elements
use commonware_parallel::{Strategy, Sequential};
let strategy = Sequential;
let numbers = vec![1, 2, 3, 4, 5];
let sum = strategy.fold(
&numbers,
|| 0, // identity
|acc, &n| acc + n, // fold: add each number
|a, b| a + b, // reduce: combine partial sums
);
assert_eq!(sum, 15);Sourcefn map_collect_vec<I, F, T>(&self, iter: I, map_op: F) -> Vec<T>
fn map_collect_vec<I, F, T>(&self, iter: I, map_op: F) -> Vec<T>
Maps each element and collects results into a Vec.
This is a convenience method that applies map_op to each element and
collects the results. For Sequential, elements are processed in order.
For Rayon, elements may be processed out of order but the final
vector preserves the original ordering.
§Arguments
iter: The collection to map overmap_op: The mapping function to apply to each element
§Examples
use commonware_parallel::{Strategy, Sequential};
let strategy = Sequential;
let data = vec![1, 2, 3, 4, 5];
let squared: Vec<i32> = strategy.map_collect_vec(&data, |&x| x * x);
assert_eq!(squared, vec![1, 4, 9, 16, 25]);Sourcefn try_map_collect_vec<I, F, T, E>(
&self,
iter: I,
map_op: F,
) -> Result<Vec<T>, E>
fn try_map_collect_vec<I, F, T, E>( &self, iter: I, map_op: F, ) -> Result<Vec<T>, E>
Maps each element with a fallible operation and collects results into a Vec.
This is a convenience method that applies map_op to each element and
collects the results into a single Result. Output ordering on success
matches map_collect_vec. Implementations may stop
applying map_op after an error is observed. When more than one element
fails, any error may be returned.
§Arguments
iter: The collection to map overmap_op: The fallible mapping function to apply to each element
§Examples
use commonware_parallel::{Strategy, Sequential};
let strategy = Sequential;
let data = vec![1, 2, 3, 4, 5];
let squared: Result<Vec<i32>, ()> = strategy.try_map_collect_vec(
&data,
|&x| Ok(x * x),
);
assert_eq!(squared, Ok(vec![1, 4, 9, 16, 25]));Sourcefn map_init_collect_vec<I, INIT, T, F, R>(
&self,
iter: I,
init: INIT,
map_op: F,
) -> Vec<R>
fn map_init_collect_vec<I, INIT, T, F, R>( &self, iter: I, init: INIT, map_op: F, ) -> Vec<R>
Maps each element with per-partition state and collects results into a Vec.
Combines map_collect_vec with per-partition
initialization like fold_init. Useful when the mapping
operation requires mutable state that should not be shared across partitions.
§Arguments
iter: The collection to map overinit: Creates the per-partition initialization valuemap_op: The mapping function:(&mut init, item) -> result
§Examples
use commonware_parallel::{Strategy, Sequential};
let strategy = Sequential;
let data = vec![1, 2, 3, 4, 5];
// Use a counter that tracks position within each partition
let indexed: Vec<(usize, i32)> = strategy.map_init_collect_vec(
&data,
|| 0usize, // Per-partition counter
|counter, &x| {
let idx = *counter;
*counter += 1;
(idx, x * 2)
},
);
assert_eq!(indexed, vec![(0, 2), (1, 4), (2, 6), (3, 8), (4, 10)]);Sourcefn map_init_collect_vec_with_multiplier<I, INIT, T, F, R>(
&self,
iter: I,
_multiplier: usize,
init: INIT,
map_op: F,
) -> Vec<R>
fn map_init_collect_vec_with_multiplier<I, INIT, T, F, R>( &self, iter: I, _multiplier: usize, init: INIT, map_op: F, ) -> Vec<R>
Maps each element with per-partition state and a per-item work multiplier.
Sourcefn map_partition_collect_vec<I, F, K, U>(
&self,
iter: I,
map_op: F,
) -> (Vec<U>, Vec<K>)
fn map_partition_collect_vec<I, F, K, U>( &self, iter: I, map_op: F, ) -> (Vec<U>, Vec<K>)
Maps each element, filtering out None results and tracking their keys.
This is a convenience method that applies map_op to each element. The
closure returns (key, Option<value>). Elements where the option is Some
have their values collected into the first vector. Elements where the option
is None have their keys collected into the second vector.
§Arguments
iter: The collection to map overmap_op: The mapping function returning(K, Option<U>)
§Returns
A tuple of (results, filtered_keys) where:
results: Values from successful mappings (wheremap_opreturnedSome)filtered_keys: Keys wheremap_opreturnedNone
§Examples
use commonware_parallel::{Strategy, Sequential};
let strategy = Sequential;
let data = vec![1, 2, 3, 4, 5];
let (evens, odd_values): (Vec<i32>, Vec<i32>) = strategy.map_partition_collect_vec(
data.iter(),
|&x| (x, if x % 2 == 0 { Some(x * 10) } else { None }),
);
assert_eq!(evens, vec![20, 40]);
assert_eq!(odd_values, vec![1, 3, 5]);Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".
Implementors§
impl Strategy for Rayon
std) and neither commonware_stability_DELTA nor commonware_stability_EPSILON nor commonware_stability_GAMMA nor commonware_stability_RESERVED only.impl Strategy for Sequential
commonware_stability_DELTA nor commonware_stability_EPSILON nor commonware_stability_GAMMA nor commonware_stability_RESERVED.impl<S: Strategy> Strategy for Manual<S>
commonware_stability_DELTA nor commonware_stability_EPSILON nor commonware_stability_GAMMA nor commonware_stability_RESERVED.