-
-
Notifications
You must be signed in to change notification settings - Fork 76
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #268 from peter-scholtens/patch-1
An examples directory is added to allow cargo to run the given exampl…
- Loading branch information
Showing
6 changed files
with
206 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
// Use the asynchronous cache. | ||
use moka::future::Cache; | ||
|
||
#[tokio::main] | ||
async fn main() { | ||
const NUM_TASKS: usize = 16; | ||
const NUM_KEYS_PER_TASK: usize = 64; | ||
|
||
fn value(n: usize) -> String { | ||
format!("value {}", n) | ||
} | ||
|
||
// Create a cache that can store up to 10,000 entries. | ||
let cache = Cache::new(10_000); | ||
|
||
// Spawn async tasks and write to and read from the cache. | ||
let tasks: Vec<_> = (0..NUM_TASKS) | ||
.map(|i| { | ||
// To share the same cache across the async tasks, clone it. | ||
// This is a cheap operation. | ||
let my_cache = cache.clone(); | ||
let start = i * NUM_KEYS_PER_TASK; | ||
let end = (i + 1) * NUM_KEYS_PER_TASK; | ||
|
||
tokio::spawn(async move { | ||
// Insert 64 entries. (NUM_KEYS_PER_TASK = 64) | ||
for key in start..end { | ||
// insert() is an async method, so await it. | ||
my_cache.insert(key, value(key)).await; | ||
// get() returns Option<String>, a clone of the stored value. | ||
assert_eq!(my_cache.get(&key), Some(value(key))); | ||
} | ||
|
||
// Invalidate every 4 element of the inserted entries. | ||
for key in (start..end).step_by(4) { | ||
// invalidate() is an async method, so await it. | ||
my_cache.invalidate(&key).await; | ||
} | ||
}) | ||
}) | ||
.collect(); | ||
|
||
// Wait for all tasks to complete. | ||
futures_util::future::join_all(tasks).await; | ||
|
||
// Verify the result. | ||
for key in 0..(NUM_TASKS * NUM_KEYS_PER_TASK) { | ||
if key % 4 == 0 { | ||
assert_eq!(cache.get(&key), None); | ||
} else { | ||
assert_eq!(cache.get(&key), Some(value(key))); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
use moka::sync::Cache; | ||
use moka::sync::ConcurrentCacheExt; | ||
use std::thread::sleep; | ||
use std::time::Duration; | ||
|
||
fn main() { | ||
// Make an artifically small cache and 1-second ttl to observe eviction listener. | ||
{ | ||
let cache = Cache::builder() | ||
.max_capacity(2) | ||
.time_to_live(Duration::from_secs(1)) | ||
.eviction_listener(|key, value, cause| { | ||
println!("Evicted ({:?},{:?}) because {:?}", key, value, cause) | ||
}) | ||
.build(); | ||
// Overload capacity of the cache. | ||
cache.insert(&0, "zero".to_string()); | ||
cache.insert(&1, "one".to_string()); | ||
cache.insert(&2, "twice".to_string()); | ||
// Due to race condition spilled over maybe evicted twice by cause | ||
// Replaced and Size. | ||
cache.insert(&2, "two".to_string()); | ||
// With 1-second ttl, keys 0 and 1 will be evicted if we wait long enough. | ||
sleep(Duration::from_secs(2)); | ||
println!("Wake up!"); | ||
cache.insert(&3, "three".to_string()); | ||
cache.insert(&4, "four".to_string()); | ||
cache.insert(&5, "five".to_string()); | ||
let _ = cache.remove(&3); | ||
cache.invalidate(&4); | ||
cache.invalidate_all(); | ||
loop { | ||
// Synchronization is limited to at most 500 entries for each call. | ||
cache.sync(); | ||
// Check if all is done. Calling entry_count() requires calling sync() first! | ||
if cache.entry_count() == 0 { | ||
break; | ||
} | ||
} | ||
cache.insert(&6, "six".to_string()); | ||
// When cache is dropped eviction listener is not called. Eiher | ||
// call invalidate_all() or wait longer than ttl. | ||
sleep(Duration::from_secs(2)); | ||
println!("Cache structure removed."); | ||
} | ||
sleep(Duration::from_secs(1)); | ||
println!("Exit program."); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
use std::convert::TryInto; | ||
use moka::sync::Cache; | ||
|
||
fn main() { | ||
let cache = Cache::builder() | ||
// A weigher closure takes &K and &V and returns a u32 representing the | ||
// relative size of the entry. Here, we use the byte length of the value | ||
// String as the size. | ||
.weigher(|_key, value: &String| -> u32 { | ||
value.len().try_into().unwrap_or(u32::MAX) | ||
}) | ||
// This cache will hold up to 32MiB of values. | ||
.max_capacity(32 * 1024 * 1024) | ||
.build(); | ||
cache.insert(0, "zero".to_string()); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
// Use the synchronous cache. | ||
use moka::sync::Cache; | ||
|
||
use std::thread; | ||
|
||
fn value(n: usize) -> String { | ||
format!("value {}", n) | ||
} | ||
|
||
fn main() { | ||
const NUM_THREADS: usize = 16; | ||
const NUM_KEYS_PER_THREAD: usize = 64; | ||
|
||
// Create a cache that can store up to 10,000 entries. | ||
let cache = Cache::new(10_000); | ||
|
||
// Spawn threads and read and update the cache simultaneously. | ||
let threads: Vec<_> = (0..NUM_THREADS) | ||
.map(|i| { | ||
// To share the same cache across the threads, clone it. | ||
// This is a cheap operation. | ||
let my_cache = cache.clone(); | ||
let start = i * NUM_KEYS_PER_THREAD; | ||
let end = (i + 1) * NUM_KEYS_PER_THREAD; | ||
|
||
thread::spawn(move || { | ||
// Insert 64 entries. (NUM_KEYS_PER_THREAD = 64) | ||
for key in start..end { | ||
my_cache.insert(key, value(key)); | ||
// get() returns Option<String>, a clone of the stored value. | ||
assert_eq!(my_cache.get(&key), Some(value(key))); | ||
} | ||
|
||
// Invalidate every 4 element of the inserted entries. | ||
for key in (start..end).step_by(4) { | ||
my_cache.invalidate(&key); | ||
} | ||
}) | ||
}) | ||
.collect(); | ||
|
||
// Wait for all threads to complete. | ||
threads.into_iter().for_each(|t| t.join().expect("Failed")); | ||
|
||
// Verify the result. | ||
for key in 0..(NUM_THREADS * NUM_KEYS_PER_THREAD) { | ||
if key % 4 == 0 { | ||
assert_eq!(cache.get(&key), None); | ||
} else { | ||
assert_eq!(cache.get(&key), Some(value(key))); | ||
} | ||
} | ||
} |