#thread-safe #key #requests #async-task #expensive #concurrency #deduplicating #waiter #broadcast-channel

coalesced_map

A thread-safe, deduplicating map that ensures expensive computations are executed only once per key

3 releases

0.1.2 Sep 5, 2025
0.1.1 Aug 15, 2025
0.1.0 Aug 12, 2025

#603 in Development tools

Download history 57/week @ 2025-08-07 1121/week @ 2025-08-14 737/week @ 2025-08-21 1436/week @ 2025-08-28 1212/week @ 2025-09-04 875/week @ 2025-09-11 536/week @ 2025-09-18 1336/week @ 2025-09-25 1624/week @ 2025-10-02 1539/week @ 2025-10-09 2094/week @ 2025-10-16 1722/week @ 2025-10-23 1169/week @ 2025-10-30 826/week @ 2025-11-06

6,052 downloads per month
Used in 2 crates (via rattler_repodata_gateway)

BSD-3-Clause

29KB
476 lines

A thread-safe, deduplicating map that ensures expensive computations are executed only once per key, even when multiple concurrent requests are made.

This map is designed for scenarios where multiple async tasks might request the same resource simultaneously. Instead of performing duplicate work, the CoalescedMap ensures that only the first request for a given key executes the initialization function, while subsequent concurrent requests wait for and receive the same result.

The implementation uses DashMap for thread-safe storage and tokio::sync::broadcast channels for coordinating between concurrent waiters.

Example

use coalesced_map::{CoalescedMap, CoalescedGetError};
use std::{sync::Arc, time::Duration};

#[tokio::main]
async fn main() {
    // Create with default hasher (RandomState)
    let cache: CoalescedMap<String, Arc<String>> = CoalescedMap::new();

    // Or create with custom hasher
    use std::collections::hash_map::RandomState;
    let hasher = RandomState::new();
    let cache_with_hasher: CoalescedMap<String, Arc<String>, RandomState> =
        CoalescedMap::with_hasher(hasher);

    // Simulate multiple concurrent requests for the same expensive resource
    let key = "expensive_computation".to_string();

    let handle1 = {
        let cache = cache.clone();
        let key = key.clone();
        tokio::spawn(async move {
            cache.get_or_try_init(key, || async {
                // Simulate expensive work (e.g., network request, file I/O)
                tokio::time::sleep(Duration::from_millis(100)).await;
                println!("Performing expensive computation...");
                Ok(Arc::new("computed_result".to_string()))
            }).await
        })
    };

    let handle2 = {
        let cache = cache.clone();
        let key = key.clone();
        tokio::spawn(async move {
            cache.get_or_try_init(key, || async {
                // This function will NOT be executed due to coalescing
                println!("This should not print!");
                Ok(Arc::new("unused".to_string()))
            }).await
        })
    };

    let result1 = handle1.await.unwrap().unwrap();
    let result2 = handle2.await.unwrap().unwrap();

    // Both results are identical (same Arc instance)
    assert!(Arc::ptr_eq(&result1, &result2));
    assert_eq!(*result1, "computed_result");
}

coalesced_map

Crates.io Documentation Build Status License

A thread-safe, deduplicating map that ensures expensive computations are executed only once per key, even when multiple concurrent requests are made.

This map is designed for scenarios where multiple async tasks might request the same resource simultaneously. Instead of performing duplicate work, the CoalescedMap ensures that only the first request for a given key executes the initialization function, while subsequent concurrent requests wait for and receive the same result.

Dependencies

~3–6.5MB
~104K SLoC