#key-value-store #thread #locks #mutex #data-structures #async

lockable

This library offers hash map, hash set and cache data structures where individual entries can be locked

10 releases

0.1.1 Nov 8, 2024
0.1.0 Nov 8, 2024
0.0.8 Jan 25, 2024
0.0.7 Dec 15, 2023
0.0.2 Apr 11, 2022

#68 in Concurrency

Download history 316/week @ 2024-08-18 309/week @ 2024-08-25 361/week @ 2024-09-01 387/week @ 2024-09-08 384/week @ 2024-09-15 767/week @ 2024-09-22 2871/week @ 2024-09-29 1066/week @ 2024-10-06 1303/week @ 2024-10-13 2312/week @ 2024-10-20 1021/week @ 2024-10-27 1157/week @ 2024-11-03 900/week @ 2024-11-10 2230/week @ 2024-11-17 932/week @ 2024-11-24 904/week @ 2024-12-01

5,083 downloads per month
Used in tonbo

MIT/Apache

340KB
4.5K SLoC

Build Status Latest Version docs.rs License License codecov unsafe forbidden

lockable

The lockable library offers thread-safe HashMap (see LockableHashMap), LruCache (see LockableLruCache) and LockPool (see LockPool) types. In all of these dat atypes, individual keys can be locked/unlocked, even if there is no entry for this key in the map or cache.

This can be very useful for synchronizing access to an underlying key-value store or for building cache data structures on top of such a key-value store.

LRU cache example

This example builds a simple LRU cache and locks some entries.

use lockable::{AsyncLimit, LockableLruCache};

let lockable_cache = LockableLruCache::<i64, String>::new();

// Insert an entry
lockable_cache.async_lock(4, AsyncLimit::no_limit())
    .await?
    .insert(String::from("Value"));

// Hold a lock on a different entry
let guard = lockable_cache.async_lock(5, AsyncLimit::no_limit())
    .await?;

// This next line would wait until the lock gets released,
// which in this case would cause a deadlock because we're
// on the same thread
// let guard2 = lockable_cache.async_lock(5, AsyncLimit::no_limit())
//    .await?;

// After dropping the corresponding guard, we can lock it again
std::mem::drop(guard);
let guard2 = lockable_cache.async_lock(5, AsyncLimit::no_limit())
    .await?;

Lockpool example

This example builds a simple lock pool using the LockPool data structure. A lock pool is a pool of keyable locks. This can be used if you don't need a cache but just some way to synchronize access to an underlying resource.

use lockable::LockPool;

let lockpool = LockPool::new();
let guard1 = lockpool.async_lock(4).await;
let guard2 = lockpool.async_lock(5).await;

// This next line would wait until the lock gets released,
// which in this case would cause a deadlock because we're
// on the same thread.
// let guard3 = lockpool.async_lock(4).await;

// After dropping the corresponding guard, we can lock it again
std::mem::drop(guard1);
let guard3 = lockpool.async_lock(4).await;

HashMap example

If you need a lockable key-value store but don't need the LRU ordering, you can use LockableHashMap.

use lockable::{AsyncLimit, LockableHashMap};

let lockable_map = LockableHashMap::<i64, String>::new();

// Insert an entry
lockable_map.async_lock(4, AsyncLimit::no_limit())
    .await?
    .insert(String::from("Value"));

// Hold a lock on a different entry
let guard = lockable_map.async_lock(5, AsyncLimit::no_limit())
    .await?;

// This next line would wait until the lock gets released,
// which in this case would cause a deadlock because we're
// on the same thread
// let guard2 = lockable_map.async_lock(5, AsyncLimit::no_limit())
//    .await?;

// After dropping the corresponding guard, we can lock it again
std::mem::drop(guard);
let guard2 = lockable_map.async_lock(5, AsyncLimit::no_limit())
    .await?;

Crate Features

License: MIT OR Apache-2.0

Dependencies

~4–10MB
~103K SLoC