Rust SkipList
A Rust implementation of the SkipList data structure, inspired by LevelDB's SkipList. This project provides a SkipList implementation with lock-free reads and locked writes, suitable for efficient key-value storage and retrieval.
Features
- Lock-free read operations
- Efficient insertion (with locking) and lookup
- Iterator support for traversal
- Configurable maximum height and branching factor
- Written in safe Rust with minimal unsafe code
- Memory management through a shared Arena allocator
- No explicit delete operation (following LevelDB's design)
Memory Management
The SkipList uses a shared Arena for memory allocation. This means:
- All nodes are allocated from the Arena
- There's no need for manual memory deallocation
- The entire SkipList is deallocated when the Arena is dropped
Usage
Add this to your Cargo.toml:
[]
= "0.3.0"
Then you can use the SkipList in your Rust code:
use ;
use Arena;
use Arc;
API
Arena
new() -> Arena: Create a new Arenaallocate(bytes: usize) -> *mut u8: Allocate memory of the specified sizeallocate_aligned(bytes: usize) -> *mut u8: Allocate memory of the specified size with alignmentmemory_usage(&self) -> usize: Get the current memory usage of the arena
SkipList<K>
-
new(arena: Arena) -> SkipList<K>: Create a new SkipListCreates and returns a new
SkipListinstance using the provided memory arena. -
insert(key: K): Insert a key into the SkipList (requires locking)Inserts the given key into the SkipList. This operation acquires a write lock to ensure thread-safe modification.
-
contains(&key: &K) -> bool: Check if a key exists in the SkipList (lock-free)Checks whether the given key exists in the SkipList. This is a lock-free operation that allows concurrent reads.
-
iter(&self) -> SkipListIterator<K>: Get an iterator over the SkipList (lock-free)Returns an iterator that can be used to traverse the elements in the SkipList. This operation is lock-free, allowing concurrent iteration with other operations.
SkipListIterator<K>
new(list: &SkipList<K>) -> SkipListIterator<K>: Create a new iterator over a SkipListvalid(&self) -> bool: Check if the iterator is pointing to a valid nodekey(&self) -> &K: Get the key of the current nodenext(&mut self): Move to the next nodeprev(&mut self): Move to the previous nodeseek(&mut self, target: &K): Seek to the first node with a key >= targetseek_to_first(&mut self): Seek to the first nodeseek_to_last(&mut self): Seek to the last node
Performance
This implementation aims to provide similar performance characteristics to LevelDB's SkipList. It uses atomic operations for concurrent read access and locking for write operations, providing a balance between concurrency and data consistency.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
This project is licensed under the MIT License.
Acknowledgments
- Inspired by LevelDB's SkipList implementation
- Built with Rust's powerful type system and memory safety guarantees