dscale 0.7.1

A fast & deterministic simulation framework for benchmarking and testing distributed systems
Documentation
// DScale: deterministic distributed systems simulator
// Copyright (C) 2026  Konstantin Shprenger

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.

use std::hint;

/// Collects values until a threshold is reached, then yields them all at once.
/// Useful for implementing quorum-based logic.
pub struct Combiner<T: Sized> {
    values: Vec<T>,
    threshold: usize,
    idx: usize,
}

impl<T: Sized> Combiner<T> {
    /// Creates a new combiner that fires after `threshold` values.
    pub fn new(threshold: usize) -> Self {
        debug_assert!(
            threshold > 0,
            "Combiner threshold should be greater than zero"
        );
        Self {
            values: Vec::with_capacity(threshold),
            threshold,
            idx: 0,
        }
    }

    /// Adds a value. Returns `Some(all_values)` when the threshold is reached,
    /// `None` otherwise. After firing, subsequent calls return `None`.
    pub fn combine(&mut self, value: T) -> Option<Vec<T>> {
        if self.idx >= self.threshold {
            hint::cold_path();
            return None;
        }

        self.values.push(value);
        self.idx += 1;

        if self.idx == self.threshold {
            hint::cold_path();
            Some(std::mem::take(&mut self.values))
        } else {
            None
        }
    }
}