### Example: String Length Weighter Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/types.md Demonstrates implementing `Weighter` for a cache where values are strings, and weight is determined by string length. This example shows how to integrate a custom weighter with `quick_cache::sync::Cache`. ```rust use quick_cache::{Weighter, sync::Cache}; #[derive(Clone)] struct StringWeighter; impl Weighter for StringWeighter { fn weight(&self, _key: &u64, val: &String) -> u64 { val.len() as u64 } } let cache = Cache::with_weighter(100, 100_000, StringWeighter); cache.insert(1, "test".to_string()); // Adds 4 units of weight ``` -------------------------------- ### Build Options with Builder Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/types.md Example demonstrating how to use OptionsBuilder to configure and build Options. Required fields like estimated_items_capacity and weight_capacity must be set. ```rust use quick_cache::OptionsBuilder; let options = OptionsBuilder::new() .estimated_items_capacity(10000) .weight_capacity(1000000) .hot_allocation(0.9) .build() .expect("Invalid options"); ``` -------------------------------- ### Sync Cache Quick Start Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/INDEX.md Demonstrates basic usage of the thread-safe `Cache` including creation, insertion, retrieval, atomic get-or-insert, and removal. ```rust use quick_cache::sync::Cache; // Create cache let cache = Cache::new(1000); // Insert cache.insert("key", "value"); // Get with hotness update assert_eq!(cache.get(&"key"), Some("value")); // Atomic get-or-insert let result = cache.get_or_insert_with(&"key2", || { Ok("computed_value") })?; // Remove cache.remove(&"key"); ``` -------------------------------- ### Unsync Cache Quick Start Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/INDEX.md Illustrates the usage of the single-threaded `Cache`, focusing on creation (requiring `&mut`), insertion, retrieval, and removal. ```rust use quick_cache::unsync::Cache; // Create cache (requires &mut) let mut cache = Cache::new(1000); // Insert cache.insert("key", "value"); // Get (returns reference, no clone) if let Some(val) = cache.get(&"key") { println!("Value: {}", val); } // Remove cache.remove(&"key"); ``` -------------------------------- ### Ghost Key Tracking Example Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/eviction-policy.md Illustrates the lifecycle of a key involving cache misses, promotions, eviction to the ghost list, and re-admission via ghost hit. ```text Request 1: key="foo" → miss, insert to cold queue Request 2: key="foo" → hit, promote to hot queue Request 3: (cache evicts "foo") → "foo" moves to ghost list Request 4: key="foo" → miss (value not cached), but ghost hit → key is immediately inserted to hot queue ``` -------------------------------- ### Single-Threaded Usage Example Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/unsync-cache.md Demonstrates basic operations on an unsync cache in a single-threaded context, requiring mutable access for all operations. ```APIDOC ## Single-Threaded Usage ### Description The unsync cache is optimized for single-threaded or single-task scenarios. All operations require `&mut self`. ### Example ```rust let mut cache = Cache::::new(1000); // All operations require &mut cache.insert("key".to_string(), 42); if let Some(val) = cache.get(&"key".to_string()) { println!("Value: {}", val); } cache.remove(&"key".to_string()); ``` **Note:** It cannot be shared between threads without manual synchronization. For multi-threaded use, use [`sync::Cache`](sync-cache.md). ``` -------------------------------- ### Initialize OptionsBuilder Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/configuration.md Create a new instance of OptionsBuilder to start configuring cache options. No options are set initially; defaults will be applied during the build process. ```rust let builder = OptionsBuilder::new(); ``` -------------------------------- ### Clock-PRO Scan Resistance Example Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/eviction-policy.md Demonstrates how Quick Cache's Clock-PRO algorithm mitigates scan pollution by using separate hot and cold queues, protecting the working set. ```text Cache with 5 items (4 hot capacity, 1 cold capacity): Get 1,2,3,4,5 Get 6,7,8,9,10 (scan) Get 1,2,3,4,5 ``` -------------------------------- ### RefMut Example Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/unsync-cache.md Demonstrates the usage of `RefMut` for mutable access to cache values, leveraging `Deref` and `DerefMut` traits. ```APIDOC ## RefMut Usage ### Description A mutable reference wrapper returned by `get_mut`, `peek_mut`, and guard insertion methods. Implements `Deref` and `DerefMut`. ### Example ```rust if let Some(mut val) = cache.get_mut(&1) { *val = new_value; // Deref auto-implemented } ``` **Warning:** Leaking this reference may cause cache weight tracking to be inaccurate because weight is recalculated when the reference is dropped. ``` -------------------------------- ### Item Movement Diagram: Promote to Hot Queue Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/eviction-policy.md Demonstrates how an item is promoted to the hot queue after a successful 'get' operation, provided the cold queue is empty. ```text [3] Get key="b" (hit) Promote "b" to hot queue Cold: [] Hot: [b] ``` -------------------------------- ### Atomic Get-Or-Insert Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/README.md Shows how to atomically get a value from the cache or compute and insert it if it's missing. Includes an example with timeout and fine control using `get_value_or_guard`. ```rust let result = cache.get_or_insert_with(&key, || { // Only called once across concurrent threads Ok(expensive_computation(&key)) })?; // Or with timeout and fine control: match cache.get_value_or_guard(&key, None) { GuardResult::Value(v) => println!("Cached: {}", v), GuardResult::Guard(guard) => { let computed = expensive_computation(&key); guard.insert(computed).ok(); } GuardResult::Timeout => println!("Timeout waiting") } ``` -------------------------------- ### Build Cache Options with OptionsBuilder Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/configuration.md Configure cache settings such as capacity, shards, and allocation strategies using the OptionsBuilder fluent interface. This example demonstrates setting estimated item capacity, weight capacity, shard count, and hot/ghost allocations before building the options and creating a cache instance. ```rust use quick_cache::{sync::Cache, OptionsBuilder, UnitWeighter, DefaultHashBuilder, DefaultLifecycle}; let options = OptionsBuilder::new() .estimated_items_capacity(10000) .weight_capacity(1_000_000) .shards(16) .hot_allocation(0.95) .ghost_allocation(0.5) .build()?; let cache = Cache::::with_options( options, UnitWeighter, DefaultHashBuilder::default(), DefaultLifecycle::default(), ); ``` -------------------------------- ### Monitoring Evictions with Lifecycle Hooks Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/eviction-policy.md Implement the `Lifecycle` trait to track eviction statistics. This example shows how to count total, hot, and cold evictions. ```rust use quick_cache::Lifecycle; struct EvictionStats { total: usize, hot: usize, cold: usize, } impl Lifecycle for EvictionStats { type RequestState = (); fn begin_request(&self) -> () {} fn on_evict_hot(&self, _: &mut (), _: K, _: V) { self.hot += 1; self.total += 1; } fn on_evict_cold(&self, _: &mut (), _: K, _: V) { self.cold += 1; self.total += 1; } } let stats = EvictionStats { total: 0, hot: 0, cold: 0 }; let cache = Cache::with(100, 1000, Default::default(), Default::default(), stats.clone()); // Use cache... println!("Total evictions: {}", stats.total); println!("Hot queue evictions: {}", stats.hot); println!("Cold queue evictions: {}", stats.cold); ``` -------------------------------- ### Tuning Cache Options for Uniform Access Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/eviction-policy.md Configure cache options for workloads with uniform access patterns where all items are equally likely to be accessed. This example reduces the benefit of the hot queue. ```rust OptionsBuilder::new() .hot_allocation(0.80) // Less benefit from hot queue .ghost_allocation(0.3) // Low; uniform access patterns .build()? ``` -------------------------------- ### Tuning Cache Options for Batch Processing Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/eviction-policy.md Configure cache options for batch processing workloads with sequential scans and one-time accesses. This example uses a larger cold queue to accommodate scans. ```rust OptionsBuilder::new() .hot_allocation(0.70) // Larger cold queue for scans .ghost_allocation(0.2) // Low; scans don't re-access .build()? ``` -------------------------------- ### Fast Inline Callback for Cache Entry Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/patterns-and-advanced.md Ensure callbacks within `entry()` are fast and do not involve external calls that could block other threads. This example shows a good practice for inline callbacks. ```rust // Good: Fast inline callback cache.entry(&key, None, |k, v| { *v += 1; EntryAction::Retain(*v) }); ``` -------------------------------- ### Memory-Constrained Cache Configuration Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/configuration.md Example configuration for a cache designed for environments with limited memory. It uses a smaller capacity, fewer shards, and minimal ghost key tracking to reduce memory footprint. ```rust let options = OptionsBuilder::new() .estimated_items_capacity(1_000) .weight_capacity(10_000) .shards(4) // Fewer shards .hot_allocation(0.80) // More aggressive eviction .ghost_allocation(0.1) // Less ghost tracking .build()?; ``` -------------------------------- ### Implement Lifecycle for Cache Eviction Listener Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/types.md Demonstrates how to implement the Lifecycle trait to listen for cache evictions. This example uses an MPSC channel to notify a listener when an item is evicted. ```rust use quick_cache::{Lifecycle, sync::Cache}; use std::sync::mpsc::Sender; struct EvictionListener { tx: Sender<(Key, Val)>; } impl Lifecycle for EvictionListener { type RequestState = (); fn begin_request(&self) -> Self::RequestState {} fn on_evict(&self, _state: &mut (), key: Key, val: Val) { let _ = self.tx.send((key, val)); } } let (tx, rx) = std::sync::mpsc::channel(); let listener = EvictionListener { tx }; let cache = Cache::with(100, 1000, Default::default(), Default::default(), listener); ``` -------------------------------- ### LRU Cache Scan Problem Example Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/eviction-policy.md Illustrates how a traditional LRU cache can be polluted by sequential scan workloads, leading to a degraded hit rate for frequently accessed items. ```text LRU Cache with capacity 5, items [1,2,3,4,5]: Get 1,2,3,4,5 Get 6,7,8,9,10 (one-time scan) Get 1,2,3,4,5 ``` -------------------------------- ### get Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/sync-cache.md Retrieves and clones a cached value. Updates key hotness for eviction purposes. Returns `Some(cloned_value)` if the key exists, otherwise `None`. ```APIDOC ## get(&self, key: &Q) -> Option ### Description Retrieves and clones a cached value. Updates key hotness for eviction purposes. ### Parameters #### Path Parameters - **key** (Q: `Hash + Equivalent`) - Required - Key to retrieve ### Returns - **Option** - `Some(cloned_value)` if the key exists, `None` otherwise. ``` -------------------------------- ### Create New Unsync Cache Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/unsync-cache.md Creates a new unsync cache with a specified capacity for items and unit weighting. Use this for a basic cache setup when custom weighting is not needed. ```rust use quick_cache::unsync::Cache; let mut cache: Cache = Cache::new(1000); ``` -------------------------------- ### High-Throughput Cache Configuration Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/configuration.md Example configuration for a cache prioritizing high throughput with a large capacity, high concurrency (many shards), and aggressive ghost key tracking for better hit rates. ```rust let options = OptionsBuilder::new() .estimated_items_capacity(100_000) .weight_capacity(10_000_000) .shards(32) // High concurrency .hot_allocation(0.95) .ghost_allocation(0.7) // Better hit rate .build()?; ``` -------------------------------- ### Tuning Cache Options for High-frequency Caching Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/eviction-policy.md Configure cache options for workloads with high-frequency access to hot items and a stable working set. This example sets a high `hot_allocation` to protect the working set. ```rust OptionsBuilder::new() .hot_allocation(0.97) // High; protect working set .ghost_allocation(0.5) // Moderate; some re-access .build()? ``` -------------------------------- ### Tuning Cache Options for Time-Series Data Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/eviction-policy.md Configure cache options for time-series data with temporal locality, where recent data is accessed more frequently. This example prioritizes protecting recent items. ```rust OptionsBuilder::new() .hot_allocation(0.95) // Protect recent items .ghost_allocation(0.3) // Low; old data rarely re-accessed .build()? ``` -------------------------------- ### Read-Only Cache Access with Peek Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/patterns-and-advanced.md Use `peek` for read-only queries to avoid affecting the cache's eviction priority. Use `get` when the lookup should mark the item as recently accessed. ```rust // For read-only queries that shouldn't affect cache state if let Some(val) = cache.peek(&key) { use_value(val); } // For lookups that should mark the item as accessed if let Some(val) = cache.get(&key) { use_value(val); } ``` -------------------------------- ### Custom String Length Weighter Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/INDEX.md Implement a custom `Weighter` to define cache capacity based on the byte length of string values. This example uses the length of the value string to determine its weight. ```rust use quick_cache::{sync::Cache, Weighter}; #[derive(Clone)] struct StringWeighter; impl Weighter for StringWeighter { fn weight(&self, _k: &String, v: &String) -> u64 { v.len() as u64 } } let cache = Cache::with_weighter(100, 100_000, StringWeighter); cache.insert("key".to_string(), "value".to_string()); // Cache capacity is 100,000 bytes of string data ``` -------------------------------- ### try_get Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/sync-cache.md Non-blocking version of `get`. Returns `Err(LockContention)` if the shard lock cannot be acquired immediately. ```APIDOC ## try_get(&self, key: &Q) -> Result, LockContention> ### Description Non-blocking version of `get`. Returns `Err(LockContention)` if the shard lock cannot be acquired immediately. ### Parameters #### Path Parameters - **key** (Q: `Hash + Equivalent`) - Required - Key to retrieve ### Returns - **Result, LockContention>** - `Ok(Some(cloned_value))` if the key exists, `Ok(None)` if not, or `Err(LockContention)` if the lock could not be acquired. ``` -------------------------------- ### Create and Use a Sync Cache Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/README.md Demonstrates how to create a synchronous cache with a specified capacity and insert/retrieve key-value pairs. ```rust use quick_cache::sync::Cache; let cache = Cache::new(1000); // 1000-item capacity cache.insert("key", "value"); assert_eq!(cache.get(&"key"), Some("value")); ``` -------------------------------- ### Get Cache Size Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/sync-cache.md Returns the current number of items stored in the cache across all shards. ```rust let cache: Cache = Cache::new(100); cache.insert(1, 10); assert_eq!(cache.len(), 1); ``` -------------------------------- ### Asynchronously Get or Insert Value Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/sync-cache.md Use `get_or_insert_async` for an asynchronous version of `get_or_insert_with`. It allows fetching the value using an async closure. ```rust let value = cache.get_or_insert_async(&key, async { Ok(fetch_from_db(key).await) }).await?; ``` -------------------------------- ### Define and Use MemoryUsed Struct Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/types.md Shows the definition of the MemoryUsed struct for tracking cache memory allocation and an example of how to retrieve and display this information. ```rust #[derive(Debug, Copy, Clone)] pub struct MemoryUsed { pub entries: usize, // Memory for entry storage pub map: usize, // Memory for hash map } impl MemoryUsed { pub fn total(&self) -> usize { self.entries + self.map } } ``` ```rust let mem = cache.memory_used(); println!("Cache uses {} bytes total", mem.total()); println!(" Entries: {}", mem.entries); println!(" Hash map: {}", mem.map); ``` -------------------------------- ### Basic Cache Usage Source: https://github.com/arthurprs/quick-cache/blob/master/README.md Demonstrates the fundamental insertion and retrieval of items in a simple cache. Ensure the cache has sufficient capacity. ```rust use quick_cache::unsync::Cache; fn main() { let mut cache = Cache::new(5); cache.insert("square", "blue"); cache.insert("circle", "black"); assert_eq!(*cache.get(&"square").unwrap(), "blue"); assert_eq!(*cache.get(&"circle").unwrap(), "black"); } ``` -------------------------------- ### Preventing Eviction with is_pinned Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/eviction-policy.md Use the `is_pinned` method in the `Lifecycle` trait to prevent specific items from being evicted. This example shows how to pin all items. ```rust fn is_pinned(&self, key: &Key, val: &Val) -> bool { // Items matching this condition are never evicted true // Example: pin everything } ``` -------------------------------- ### Create an Unsync Cache Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/README.md Shows how to create an asynchronous (unsync) cache with a specified capacity and insert/retrieve key-value pairs. ```rust use quick_cache::unsync::Cache; let mut cache = Cache::new(1000); cache.insert("key", "value"); assert_eq!(cache.get(&"key"), Some(&"value")); ``` -------------------------------- ### Get Cache Item Count Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/unsync-cache.md Returns the current number of items stored in the unsync cache. Use this to monitor the cache's size. ```rust let mut cache: Cache = Cache::new(100); cache.insert(1, 10); assert_eq!(cache.len(), 1); ``` -------------------------------- ### Create a Simple Cache with Unit Weighting Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/configuration.md Instantiate a cache with default unit weighting, suitable for cases where each item has a uniform weight. This is a convenience method for common scenarios. ```rust let cache = Cache::::new(items_capacity); ``` -------------------------------- ### Document Organization Structure Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/README.md Illustrates the hierarchical organization of the Quick-Cache documentation, showing how different modules are linked from the main index. ```markdown INDEX.md (start here) ├─→ sync-cache.md (thread-safe API) ├─→ unsync-cache.md (single-threaded API) ├─→ types.md (all types) ├─→ configuration.md (building and tuning) ├─→ eviction-policy.md (Clock-PRO deep dive) └─→ patterns-and-advanced.md (real-world usage) ``` -------------------------------- ### Create a Cache with Options Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/sync-cache.md Creates a cache instance using a pre-built Options struct, allowing for comprehensive configuration of capacity, weighting, hashing, and lifecycle. ```rust use quick_cache::{sync::{Cache, DefaultLifecycle}, OptionsBuilder, UnitWeighter, DefaultHashBuilder}; let cache = Cache::::with_options( OptionsBuilder::new() .estimated_items_capacity(10000) .weight_capacity(10000) .build() .unwrap(), UnitWeighter, DefaultHashBuilder::default(), DefaultLifecycle::default(), ); ``` -------------------------------- ### Create Cache from Pre-built Options Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/configuration.md Instantiate a cache using a pre-configured Options object, along with specified weighter, hash builder, and lifecycle handlers. This is useful when options are built dynamically or shared. ```rust let cache = Cache::with_options( options, weighter, hash_builder, lifecycle, ); ``` -------------------------------- ### Get Mutable Cache Value Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/unsync-cache.md Retrieves a mutable reference to a cached value and updates its hotness. Use when you need to modify an existing cached item. ```rust if let Some(mut val) = cache.get_mut(&1) { *val += 1; } ``` -------------------------------- ### Item Movement Diagram: Initial State Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/eviction-policy.md Shows the initial state of the cache with a capacity of 5, split into 4 hot and 1 cold queue, before any items are inserted. ```text Initial: capacity=5 (4 hot, 1 cold) [1] Insert key="a", value=100 (capacity not exceeded) Cold: [a] Hot: [] ``` -------------------------------- ### Custom Hash Builder Configuration Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/configuration.md Shows how to provide a custom hash builder, such as `std::collections::hash_map::RandomState`, during cache initialization. ```rust use std::collections::hash_map::RandomState; let cache = Cache::with( capacity, weight, weighter, RandomState::default(), lifecycle, ); ``` -------------------------------- ### Get Mutable or Insert with Computation Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/unsync-cache.md Similar to `get_or_insert_with`, but returns a mutable reference to the cached value. Useful when you need to modify the value immediately after retrieval or insertion. ```rust let result = cache.get_mut_or_insert_with(&1, || { Ok("computed_value".to_string()) })?; ``` -------------------------------- ### Cache::with Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/unsync-cache.md Creates a cache with all customization parameters, including estimated item capacity, weight capacity, a custom weighter, hash builder, and lifecycle hooks. ```APIDOC ## Cache::with ### Description Creates a cache with all customization parameters. ### Method `with(estimated_items_capacity: usize, weight_capacity: u64, weighter: We, hash_builder: B, lifecycle: L) -> Self` ### Parameters - **estimated_items_capacity** (usize) - Estimated number of items - **weight_capacity** (u64) - Maximum total weight - **weighter** (We) - Custom weighter implementation - **hash_builder** (B) - Custom hash builder - **lifecycle** (L) - Custom lifecycle hooks ``` -------------------------------- ### Cache with Custom Item Weights Source: https://github.com/arthurprs/quick-cache/blob/master/README.md Illustrates how to create a cache with custom item weights, using the string length of the value as the weight. Be cautious about zero weights. ```rust use quick_cache::{Weighter, sync::Cache}; #[derive(Clone)] struct StringWeighter; impl Weighter for StringWeighter { fn weight(&self, _key: &u64, val: &String) -> u64 { // Be cautious about zero weights! val.len() as u64 } } fn main() { let cache = Cache::with_weighter(100, 100_000, StringWeighter); cache.insert(1, "1".to_string()); cache.insert(54, "54".to_string()); cache.insert(1000, "1000".to_string()); assert_eq!(cache.get(&1000).unwrap(), "1000"); } ``` -------------------------------- ### Cache Construction: Shorthand Method Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/configuration.md Creates a new cache instance using a simplified constructor that accepts an estimated item capacity. This method uses default settings for other configuration options. ```rust let cache = Cache::new(1000); ``` -------------------------------- ### Custom Weighter with Full Configuration Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/configuration.md Demonstrates creating a custom weighter that calculates cache item size based on the byte length of the value. This snippet shows how to configure cache options like estimated capacity, weight capacity, shard count, and allocation percentages before building the cache. ```rust let options = OptionsBuilder::new() .estimated_items_capacity(50_000) .weight_capacity(500_000_000) // 500 MB in units .shards(16) .hot_allocation(0.97) .ghost_allocation(0.5) .build()?; #[derive(Clone)] struct ByteSizeWeighter; impl Weighter> for ByteSizeWeighter { fn weight(&self, _k: &String, v: &Vec) -> u64 { v.len() as u64 } } let cache = Cache::with_options( options, ByteSizeWeighter, DefaultHashBuilder::default(), DefaultLifecycle::default(), ); ``` -------------------------------- ### Cache Construction: With Weighter Method Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/configuration.md Constructs a cache instance by providing the estimated item capacity, weight capacity, and a custom weighter. This method allows for basic capacity and custom weight configuration. ```rust let cache = Cache::with_weighter(1000, 10000, MyWeighter); ``` -------------------------------- ### Get Mutable Reference or Guard for Insertion Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/unsync-cache.md Returns a mutable reference to a cached value if it exists, otherwise returns a `Guard` for insertion. This allows for conditional modification or insertion of cache entries. ```rust let result = cache.get_mut_or_guard(&1); ``` -------------------------------- ### Get or Insert with Computation Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/unsync-cache.md Atomically retrieves a cached value or computes and inserts one if it's not present. Returns a `Result` which can contain the value, indicate it was not admitted, or signal an error during computation. ```rust let result = cache.get_or_insert_with(&1, || { Ok("computed_value".to_string()) })?; if let Some(value) = result { println!("Value: {}", value); } ``` -------------------------------- ### Cache Construction: Full Method Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/configuration.md Builds a cache instance by specifying item capacity, weight capacity, a custom weighter, a hash builder, and a lifecycle manager. This method offers more control over cache behavior. ```rust let cache = Cache::with( 1000, 10000, MyWeighter, DefaultHashBuilder::default(), DefaultLifecycle::default(), ); ``` -------------------------------- ### Single-Threaded Unsync Cache Initialization Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/configuration.md Demonstrates initializing an unsynchronized cache for single-threaded use cases. It specifies capacity, weight, a default hash builder, and default lifecycle management. ```rust use quick_cache::unsync::Cache; let mut cache = Cache::with_options( OptionsBuilder::new() .estimated_items_capacity(5_000) .weight_capacity(100_000) .shards(1) .build()?, UnitWeighter, DefaultHashBuilder::default(), DefaultLifecycle::default(), ); ``` -------------------------------- ### Create Unsync Cache with Options Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/unsync-cache.md Creates a fully customized unsync cache using an `Options` struct, allowing configuration of capacity, weighting, hashing, and lifecycle hooks. This is suitable for advanced use cases requiring fine-tuned cache behavior. ```rust use quick_cache::{unsync::{Cache, DefaultLifecycle}, OptionsBuilder, UnitWeighter, DefaultHashBuilder}; let mut cache = Cache::::with_options( OptionsBuilder::new() .estimated_items_capacity(10000) .weight_capacity(10000) .build() .unwrap(), UnitWeighter, DefaultHashBuilder::default(), DefaultLifecycle::default(), ); ``` -------------------------------- ### Atomic Inspect-and-Act with Entry API Source: https://github.com/arthurprs/quick-cache/blob/master/README.md Shows how to use the `entry` API for atomic operations like inserting if absent or conditionally removing entries. Handles both insertion and removal logic. ```rust use quick_cache::sync::{Cache, EntryAction, EntryResult}; fn main() { let cache: Cache = Cache::new(100); // Insert-or-get: if absent, compute and insert; if present, return cached let result = cache.entry(&0, None, |_key, val| EntryAction::Retain(*val)); let value = match result { EntryResult::Retained(v) => v, EntryResult::Vacant(guard) => { let v = 42; // expensive computation guard.insert(v).unwrap(); v } _ => unreachable!(), }; assert_eq!(value, 42); // Conditionally remove: evict entries below a threshold let result = cache.entry(&0, None, |_key, val| { if *val < 100 { EntryAction::<()>::Remove } else { EntryAction::Retain(()) } }); assert!(matches!(result, EntryResult::Removed(0, 42))); } ``` -------------------------------- ### Item Movement Diagram: Insert into Cold and Hot Queues Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/eviction-policy.md Shows the state of the cache after inserting new items into both the cold and hot queues. ```text [4] Insert key="c", value=300 Cold: [c] Hot: [b] [5] Insert key="d", value=400 Cold: [d] (evict "c" Hot: [b] ``` -------------------------------- ### Custom Lifecycle (Eviction Listener) Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/README.md Demonstrates implementing a custom lifecycle hook to listen for cache eviction events. Evicted items are sent through a channel. ```rust use quick_cache::{sync::Cache, Lifecycle}; use std::sync::mpsc::Sender; struct EvictionListener { tx: Sender<(K, V)>, } impl Lifecycle for EvictionListener { type RequestState = (); fn begin_request(&self) -> () {} fn on_evict(&self, _: &mut (), k: K, v: V) { let _ = self.tx.send((k, v)); } } let (tx, rx) = std::sync::mpsc::channel(); let listener = EvictionListener { tx }; let cache = Cache::with(100, 1000, Default::default(), Default::default(), listener); cache.insert(1, "value"); // When evicted, sends (1, "value") through channel if let Ok((k, v)) = rx.recv() { println!("Evicted: {} -> {}", k, v); } ``` -------------------------------- ### get_or_insert_with Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/sync-cache.md Atomically gets a cached value or computes and inserts one. Only one thread computes the value even with concurrent calls. Others wait for insertion. Returns `Ok(value)` or `Err(E)`. ```APIDOC ## get_or_insert_with(&self, key: &Q, with: impl FnOnce() -> Result) -> Result ### Description Atomically gets a cached value or computes and inserts one. Only one thread computes the value even with concurrent calls. Others wait for insertion. ### Parameters #### Path Parameters - **key** (Q: `Hash + Equivalent`) - Required - Cache key - **with** (FnOnce() -> Result) - Required - Closure to compute value on miss ### Returns - **Result** - `Ok(value)` if found or inserted, or `Err(E)` if the computation failed. ``` -------------------------------- ### entry_async Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/sync-cache.md Asynchronous version of `entry`. ```APIDOC ## entry_async<'a, Q, T> ### Description Async version of `entry`. ### Method `entry_async` ### Parameters #### Path Parameters - **key** (Q) - Required - Cache key - **on_occupied** (impl FnOnce(&Key, &mut Val) -> EntryAction) - Required - Callback on existing entry ### Response - `EntryResult<'a, ...>` ``` -------------------------------- ### Get Reference or Guard for Insertion Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/unsync-cache.md Returns a reference to a cached value if it exists, otherwise returns a `Guard` that can be used to insert the value. This is useful for managing cache entries that might not exist and require computation. ```rust match cache.get_ref_or_guard(&1) { Ok(value) => println!("Cached: {}", value), Err(guard) => { let computed = expensive_fn(); guard.insert(computed); } } ``` -------------------------------- ### Non-Blocking Cache Get with Retry and Backoff Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/patterns-and-advanced.md Implement non-blocking cache access for latency-sensitive code using `try_get` with a retry mechanism and exponential backoff. This pattern avoids blocking threads when contention occurs. ```rust use std::time::Duration; use std::thread; let mut attempt = 0; loop { match cache.try_get(&key) { Ok(Some(val)) => return val, Ok(None) => return default_value(), Err(LockContention) => { attempt += 1; if attempt > 3 { return default_value(); } thread::sleep(Duration::from_micros(attempt as u64 * 10)); } } } ``` -------------------------------- ### Get Value from Unsync Cache Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/unsync-cache.md Retrieves a reference to the value associated with a key from the unsync cache. This operation updates the key's hotness, influencing eviction priority. Returns `None` if the key is not found. ```rust if let Some(value) = cache.get(&1) { println!("Value: {}", value); } ``` -------------------------------- ### Get Value or Guard (Synchronous) Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/sync-cache.md Retrieves a cached value or a guard to insert one. Other threads will wait for insertion if a guard is returned. Use when you need to access a value or prepare to insert it, potentially blocking until the value is available or insertion is complete. ```rust match cache.get_value_or_guard(&1, None) { GuardResult::Value(v) => println!("Cached: {}", v), GuardResult::Guard(guard) => { let computed = expensive_fn(); guard.insert(computed); } GuardResult::Timeout => {/* retry */} } ``` -------------------------------- ### Document Format Conventions Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/README.md Details the standard formatting conventions used across all Quick-Cache documentation files, including markdown, code blocks, tables, and cross-references. ```markdown - **Markdown** format for readability - **Code blocks** with language hints (```rust) - **Tables** for quick reference - **Fenced sections** for examples - **Cross-references** via markdown links - **Source file references** (e.g., `src/sync.rs:65`) ``` -------------------------------- ### Create Cache with Full Customization Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/configuration.md Construct a cache instance with complete control over all components, including custom weighter, hash builder, and lifecycle management. This is for advanced use cases requiring specific hashing or item lifecycle behavior. ```rust let cache = Cache::with( estimated_items_capacity, weight_capacity, custom_weighter, custom_hash_builder, custom_lifecycle, ); ``` -------------------------------- ### Configure Ghost Allocation for Memory Efficiency Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/patterns-and-advanced.md Shows how to configure the `ghost_allocation` option. Setting it too high can waste memory for ghost tracking. Tune this value based on your workload; the default of 0.5 is usually suitable. ```rust // Uses lots of memory for ghost tracking OptionsBuilder::new() .ghost_allocation(0.9) .build()?; ``` -------------------------------- ### Cache::new Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/sync-cache.md Creates a new cache instance with a specified estimated capacity and unit weighting. ```APIDOC ## Cache::new ### Description Creates a new cache holding approximately `items_capacity` items with unit weighting. ### Method `new(items_capacity: usize) -> Self` ### Parameters #### Path Parameters - **items_capacity** (usize) - Required - Estimated number of items the cache will hold ### Returns A new `Cache` instance ### Example ```rust use quick_cache::sync::Cache; let cache: Cache = Cache::new(1000); ``` ``` -------------------------------- ### Collecting Cache Items for Analysis Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/patterns-and-advanced.md Create a snapshot of all cache items into a vector for analysis. This allows calculating metrics like the total weight of items currently in the cache. ```rust let snapshot: Vec<(K, V)> = cache.iter().collect(); let total_weight: u64 = snapshot.iter().map(|(k, v)| weighter.weight(k, v)).sum(); println!("Cache has {} items, {} weight", snapshot.len(), total_weight); ``` -------------------------------- ### Create a New Cache with Unit Weighting Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/sync-cache.md Creates a new cache instance with a specified capacity for items, using unit weighting. ```rust use quick_cache::sync::Cache; let cache: Cache = Cache::new(1000); ``` -------------------------------- ### Default Lifecycle Implementation Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/unsync-cache.md A basic `Lifecycle` implementation for unsync caches, providing API consistency without special behavior. ```rust pub struct DefaultLifecycle(std::marker::PhantomData<(Key, Val)>); impl Lifecycle for DefaultLifecycle { type RequestState = (); // ... } ``` -------------------------------- ### Basic Single-Threaded Cache Operations Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/unsync-cache.md Demonstrates fundamental cache operations (creation, insertion, retrieval, removal) in a single-threaded context. All operations require a mutable reference to the cache. ```rust let mut cache = Cache::::new(1000); // All operations require &mut cache.insert("key".to_string(), 42); if let Some(val) = cache.get(&"key".to_string()) { println!("Value: {}", val); } cache.remove(&"key".to_string()); ``` -------------------------------- ### Create Cache with Custom Weighter Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/configuration.md Initialize a cache using a custom weighter function to define item weights, alongside specified capacities. This allows for fine-grained control over memory usage based on item content. ```rust let cache = Cache::with_weighter( estimated_items_capacity, weight_capacity, custom_weighter, ); ``` -------------------------------- ### Compute and Insert with get_or_insert_with Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/patterns-and-advanced.md Use `get_or_insert_with` for a simple, atomic way to compute and insert a value into the cache. The closure is executed only once if the key is not present, and other threads will wait for its completion. ```rust let value = cache.get_or_insert_with(&key, || { Ok(expensive_computation(&key)) })?; ``` -------------------------------- ### Cache::new Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/unsync-cache.md Creates a new unsync cache with a specified approximate capacity for items. It uses unit weighting by default. ```APIDOC ## Cache::new ### Description Creates a new cache holding approximately `items_capacity` items with unit weighting. ### Method `new(items_capacity: usize) -> Self` ### Parameters - **items_capacity** (usize) - Estimated number of items ### Request Example ```rust use quick_cache::unsync::Cache; let mut cache: Cache = Cache::new(1000); ``` ``` -------------------------------- ### get_or_insert_async Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/sync-cache.md Async version of `get_or_insert_with`. ```APIDOC ## get_or_insert_async(&self, key: &Q, with: impl Future>) -> Result ### Description Async version of `get_or_insert_with`. ### Parameters #### Path Parameters - **key** (Q: `Hash + Equivalent`) - Required - Cache key - **with** (impl Future>) - Required - Future to compute value on miss ### Returns - **Result** - `Ok(value)` if found or inserted, or `Err(E)` if the computation failed. ``` -------------------------------- ### Cache::with_options Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/unsync-cache.md Creates a cache using an Options struct, which is typically built using OptionsBuilder for a more declarative configuration. ```APIDOC ## Cache::with_options ### Description Creates a cache from an `Options` struct built with `OptionsBuilder`. ### Method `with_options(options: Options, weighter: We, hash_builder: B, lifecycle: L) -> Self` ### Parameters - **options** (Options) - Cache configuration options - **weighter** (We) - Custom weighter implementation - **hash_builder** (B) - Custom hash builder - **lifecycle** (L) - Custom lifecycle hooks ### Request Example ```rust use quick_cache::{unsync::{Cache, DefaultLifecycle}, OptionsBuilder, UnitWeighter, DefaultHashBuilder}; let mut cache = Cache::::with_options( OptionsBuilder::new() .estimated_items_capacity(10000) .weight_capacity(10000) .build() .unwrap(), UnitWeighter, DefaultHashBuilder::default(), DefaultLifecycle::default(), ); ``` ``` -------------------------------- ### Zero-Weight Items for Pinned Cache Entries Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/patterns-and-advanced.md Create a `Weighter` that returns `0` for specific keys to make items 'pinned'. Pinned items do not consume weight capacity and are never evicted automatically, useful for essential configuration or metadata. ```Rust #[derive(Clone)] struct ConfigWeighter; impl Weighter for ConfigWeighter { fn weight(&self, key: &String, _val: &Config) -> u64 { if key == "global_config" { 0 // Never evict } else { 1 } } } ``` -------------------------------- ### Cache Construction: Via OptionsBuilder Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/configuration.md Creates a cache instance using a pre-configured OptionsBuilder object. This method provides the most flexibility, allowing detailed configuration of all cache parameters before instantiation. ```rust let options = OptionsBuilder::new() .estimated_items_capacity(1000) .weight_capacity(10000) .build()?; let cache = Cache::with_options( options, MyWeighter, DefaultHashBuilder::default(), DefaultLifecycle::default(), ); ``` -------------------------------- ### Create Unsync Cache with Custom Weighter Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/unsync-cache.md Creates an unsync cache with custom item weights, allowing for more granular control over eviction based on value size. Requires implementing the `Weighter` trait. ```rust use quick_cache::{unsync::Cache, Weighter}; #[derive(Clone)] struct StringWeighter; impl Weighter for StringWeighter { fn weight(&self, _key: &u64, val: &String) -> u64 { val.len() as u64 } } let mut cache = Cache::with_weighter(100, 100_000, StringWeighter); cache.insert(1, "test".to_string()); ``` -------------------------------- ### Item Movement Diagram: Ghost Hit and Promotion Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/eviction-policy.md Illustrates a 'ghost hit' scenario where an item, previously evicted and present in the ghost list, is re-inserted into the hot queue. ```text [6] Get key="c" (ghost hit!) "c" was in ghost list; insert to hot queue Cold: [d] Hot: [b, c] ``` -------------------------------- ### Enable Statistics Tracking Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/configuration.md Demonstrates how to access cache statistics like hits and misses when the 'stats' feature is enabled. Statistics tracking is disabled by default for performance. ```rust #[cfg(feature = "stats")] let hits = cache.hits(); let misses = cache.misses(); ``` -------------------------------- ### Options Struct Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/types.md Cache configuration struct. Fields are read-only after construction. Use OptionsBuilder to create instances. ```rust pub struct Options { pub(crate) shards: usize, pub(crate) hot_allocation: f64, pub(crate) ghost_allocation: f64, pub(crate) estimated_items_capacity: usize, pub(crate) weight_capacity: u64, } ``` -------------------------------- ### OptionsBuilder Struct Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/types.md Builder for constructing Options. Provides methods for setting cache configuration parameters like shards, allocations, and capacities. ```rust pub struct OptionsBuilder { shards: Option, hot_allocation: Option, ghost_allocation: Option, estimated_items_capacity: Option, weight_capacity: Option, } impl OptionsBuilder { pub fn new() -> Self { /* ... */ } pub fn shards(&mut self, shards: usize) -> &mut Self { /* ... */ } pub fn hot_allocation(&mut self, hot_allocation: f64) -> &mut Self { /* ... */ } pub fn ghost_allocation(&mut self, ghost_allocation: f64) -> &mut Self { /* ... */ } pub fn estimated_items_capacity(&mut self, capacity: usize) -> &mut Self { /* ... */ } pub fn weight_capacity(&mut self, capacity: u64) -> &mut Self { /* ... */ } pub fn build(&self) -> Result { /* ... */ } } ``` -------------------------------- ### Build Options with Invalid Ghost Allocation Source: https://github.com/arthurprs/quick-cache/blob/master/_autodocs/configuration.md Demonstrates a panic scenario when `ghost_allocation` is set outside the valid range of 0.0 to 1.0. This should be avoided during configuration. ```rust OptionsBuilder::new() .hot_allocation(1.5) // Panics: outside [0, 1] .build() ```