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/>.

/// Thread-safe key-value store shared across all processes.
pub mod kv;
pub(crate) mod process_access;
mod topology;
mod tso;

use std::any::Any;
use std::cell::RefCell;
use std::sync::Arc;
use std::sync::atomic::AtomicUsize;

use dashmap::DashMap;
pub use process_access::broadcast;
pub use process_access::broadcast_within_pool;
pub use process_access::choose_from_pool;
pub use process_access::now;
pub use process_access::pid;
pub use process_access::schedule_timer_after;
pub use process_access::send_random;
pub use process_access::send_random_from_pool;
pub use process_access::send_to;

use rustc_hash::FxBuildHasher;
pub use topology::list_pool;
pub use tso::unique_id;

use crate::services::process_access::PROCESS_ACCESS;
use crate::topology::Topology;

thread_local! {
    pub(super) static SERVICES: RefCell<Option<Arc<Services>>> = RefCell::new(None);
}

type AnyAllocated = Box<dyn Any + Send + Sync>;
type FastKV = DashMap<String, AnyAllocated, FxBuildHasher>;

pub(crate) struct Services {
    topology: Arc<Topology>,
    tso: AtomicUsize,
    kv: FastKV,
}

pub(super) fn with_services<R>(f: impl FnOnce(&Arc<Services>) -> R) -> R {
    SERVICES.with_borrow_mut(|opt| f(opt.as_ref().expect("services are not initialized")))
}

pub(crate) fn setup_services(services: Arc<Services>) {
    SERVICES.set(Some(services));
}

impl Services {
    pub(crate) fn new(topology: Arc<Topology>) -> Self {
        Self {
            topology,
            tso: AtomicUsize::new(0),
            kv: FastKV::with_hasher(FxBuildHasher),
        }
    }
}

pub(crate) fn reset() {
    SERVICES.take();
    PROCESS_ACCESS.take();
}