| Crates.io | quick-bool |
| lib.rs | quick-bool |
| version | 0.1.0 |
| created_at | 2025-08-16 20:01:44.272164+00 |
| updated_at | 2025-08-16 20:01:44.272164+00 |
| description | A lock-free boolean implementation using atomic operations |
| homepage | |
| repository | https://github.com/jdx/quick-bool |
| max_upload_size | |
| id | 1798817 |
| size | 64,207 |
A lock-free boolean implementation using atomic operations for high-performance lazy evaluation.
(right now this is experimental and I'm not sure I can actually get it to be faster than LazyLock)
QuickBool is a lightweight, lock-free alternative to LazyLock<bool> that uses atomic operations instead of mutexes for synchronization. It provides a 3-way boolean state:
Once set to true or false, the value cannot be changed, making it effectively immutable after initialization.
MIT License - see LICENSE file for details.
QuickBool is now the fastest implementation for both first access and cached access, while maintaining all its additional features:
xychart-beta
title "First Access Performance Comparison"
x-axis "Implementation" ["LazyLock", "OnceLock", "QuickBool"]
y-axis "Time (nanoseconds)" 0 --> 6
BAR [4.366, 4.755, 1.207]
xychart-beta
title "Cached Access Performance"
x-axis "Implementation" ["LazyLock", "OnceLock", "QuickBool"]
y-axis "Time (nanoseconds)" 0 --> 1
BAR [0.291, 0.438, 0.275]
Add quick-bool to your Cargo.toml:
[dependencies]
quick-bool = "0.1.0"
use quick_bool::QuickBool;
let quick_bool = QuickBool::new();
// First access computes the value
let value = quick_bool.get_or_set(|| {
// Expensive computation here
std::thread::sleep(std::time::Duration::from_millis(100));
true
});
// Subsequent access returns the cached value immediately
let cached_value = quick_bool.get_or_set(|| panic!("This won't execute"));
assert_eq!(value, cached_value);
use quick_bool::QuickBool;
let qb = QuickBool::new();
// Check if value has been computed
assert!(!qb.is_set());
// Get current value without computing
assert_eq!(qb.get(), None);
// Compute the value
qb.get_or_set(|| false);
// Now it's set
assert!(qb.is_set());
assert_eq!(qb.get(), Some(false));
use quick_bool::QuickBool;
let qb = QuickBool::new();
qb.get_or_set(|| true);
assert!(qb.is_set());
// Reset to allow recomputation
qb.reset();
assert!(!qb.is_set());
// Can compute again
let new_value = qb.get_or_set(|| false);
assert_eq!(new_value, false);
use quick_bool::QuickBool;
use std::sync::Arc;
use std::thread;
let qb = Arc::new(QuickBool::new());
let mut handles = vec![];
// Spawn multiple threads
for _ in 0..4 {
let qb_clone = Arc::clone(&qb);
let handle = thread::spawn(move || {
qb_clone.get_or_set(|| {
// This expensive computation only happens once
// across all threads
std::thread::sleep(std::time::Duration::from_millis(50));
true
})
});
handles.push(handle);
}
// Wait for all threads
let results: Vec<bool> = handles.into_iter()
.map(|h| h.join().unwrap())
.collect();
// All threads get the same result
assert!(results.iter().all(|&x| x));
For maximum performance when you know the value is cached:
use quick_bool::QuickBool;
let qb = QuickBool::new();
qb.get_or_set(|| expensive_computation());
// Fast cached access when you know it's set
if let Some(value) = qb.get() {
// Fast cached access (270 ps)
println!("Value: {}", value);
}
Contributions are welcome! Please feel free to submit a Pull Request.