Skip to main content

Module supplier

Module supplier 

Source
Expand description

§Read-only Supplier Types

Provides read-only supplier implementations that generate and return values without modifying their own state.

§Overview

A Supplier is a functional abstraction that generates values without accepting input or modifying its own state. Unlike Supplier, it uses &self instead of &mut self, enabling usage in read-only contexts and lock-free concurrent access.

§Key Differences from Supplier

AspectSupplierSupplier
self signature&mut self&self
Closure typeFnMut() -> TFn() -> T
Can modify stateYesNo
Arc implementationArc<Mutex<FnMut>>Arc<Fn> (lock-free!)
Use casesCounter, generatorFactory, constant, high concurrency

§Three Implementations

  • BoxSupplier<T>: Single ownership using Box<dyn Fn() -> T>. Zero overhead, cannot be cloned. Best for one-time use in read-only contexts.

  • ArcSupplier<T>: Thread-safe shared ownership using Arc<dyn Fn() -> T + Send + Sync>. Lock-free - no Mutex needed! Can be cloned and sent across threads with excellent performance.

  • RcSupplier<T>: Single-threaded shared ownership using Rc<dyn Fn() -> T>. Can be cloned but not sent across threads. Lightweight alternative to ArcSupplier.

§Use Cases

§1. Calling in &self Methods

use qubit_function::{ArcSupplier, Supplier};

struct Executor<E> {
    error_supplier: ArcSupplier<E>,
}

impl<E> Executor<E> {
    fn execute(&self) -> Result<(), E> {
        // Can call directly in &self method!
        Err(self.error_supplier.get())
    }
}

§2. High-Concurrency Lock-Free Access

use qubit_function::{ArcSupplier, Supplier};
use std::thread;

let factory = ArcSupplier::new(|| {
    String::from("Hello, World!")
});

let handles: Vec<_> = (0..10)
    .map(|_| {
        let f = factory.clone();
        thread::spawn(move || f.get()) // Lock-free!
    })
    .collect();

for h in handles {
    assert_eq!(h.join().unwrap(), "Hello, World!");
}

§3. Fixed Factories

use qubit_function::{BoxSupplier, Supplier};

#[derive(Clone)]
struct Config {
    timeout: u64,
}

let config_factory = BoxSupplier::new(|| Config {
    timeout: 30,
});

assert_eq!(config_factory.get().timeout, 30);
assert_eq!(config_factory.get().timeout, 30);

§Performance Comparison

For stateless scenarios in multi-threaded environments:

  • ArcSupplier<T>: Requires Mutex, lock contention on every get() call
  • ArcSupplier<T>: Lock-free, can call get() concurrently without contention

Benchmark results show ArcSupplier can be 10x faster than ArcSupplier in high-concurrency scenarios.

§Author

Haixing Hu

Structs§

ArcSupplier
Thread-safe shared ownership read-only supplier.
BoxSupplier
Box-based single ownership read-only supplier.
RcSupplier
Single-threaded shared ownership read-only supplier.

Traits§

Supplier
Read-only supplier trait: generates values without modifying state.