<div align="center">
<h1>Attachable Slab Allocator 🦀</h1>
[![crate][crate-badge]][crate-link]
![Test Status][git-ci]
![Lines of Code][total-lines]
![Repo Size][repo-size]
[](LICENSE)
[![Docs][docs-image]][docs-link]
</div>
<p><strong>
A high-performance, $O(1)$, Master-Slave slab allocator designed for `no_std` environments, kernels, and embedded systems. This library provides fixed-size memory management with RAII safety while remaining completely agnostic of the underlying memory provider.
</strong></p>
## 📖 Table of Contents
- [Core Philosophy](#-core-philosophy)
- [Key Features](#-key-features)
- [Installation](#-installation)
- [The Bridge (Setup)](#-the-bridge-setup)
- [Quick Start](#-quick-start)
- [Deep Dive: Master-Slave Architecture](#-deep-dive-master-slave-architecture)
- [Safety & Constraints (Important!)](#-safety--constraints-important)
- [Error Handling](#-error-handling)
- [License](#-license)
---
## 🛠 Core Philosophy
The **Attachable Slab Allocator** logic is built on a "Plug-and-Play" model. It knows how to divide memory into slots, but it does **not** know where that memory comes from. You "attach" the allocator to your system (be it a heap, a static pool, or hardware pages) by providing two allocation hooks.
## ✨ Key Features
- **$O(1)$ Complexity**: Allocation and deallocation are constant-time operations.
- **RAII Memory Management**: Uses `SlabBox<T>`, a smart pointer that returns memory to the slab automatically when dropped.
- **Master-Slave Hierarchy**: Automatically grows by allocating "Slave" slabs when the "Master" is full.
- **Location Independence**: Deallocate a `SlabBox` anywhere! The box finds its parent slab using a high-speed bitmask trick ($Alignment == Size$).
- **No-Std First**: Designed for environments without a standard library.
- **Pluggable Locks**: Use `SpinLock` for multi-threaded safety, or `NoLock` for maximum performance on single-core/interrupt-driven systems.
---
## 📦 Installation
Add this to your `Cargo.toml`:
```toml
[dependencies]
attachable-slab-allocator = "0.1.0"
```
---
## 🌉 The Bridge (Setup)
Before the library can be used, you **must** define how it acquires raw slabs from your system. If you skip this step, your project will fail to link.
Use the `define_allocation_hooks!` macro to connect your allocator:
```rust
use std::alloc::{alloc, dealloc, Layout};
use core::ptr::NonNull;
use attachable_slab_allocator::{define_allocation_hooks, Result};
// 1. Define your raw allocation functions
unsafe fn system_alloc(layout: Layout) -> Option<NonNull<u8>> {
let ptr = unsafe { alloc(layout) };
NonNull::new(ptr)
}
unsafe fn system_free(ptr: NonNull<u8>, layout: Layout) -> Result<()> {
unsafe { dealloc(ptr.as_ptr(), layout) };
Ok(())
}
// 2. Register them globally (Once in your main.rs or lib.rs)
define_allocation_hooks!(system_alloc, system_free);
```
---
## 🚀 Quick Start
```rust
use attachable_slab_allocator::{SlabCache, locks::SpinLock};
struct MyConfig {
id: u32,
data: [u8; 60],
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Initialize a cache for MyConfig.
// SLAB_SIZE (4096) must be a power of two!
let mut cache = SlabCache::<MyConfig, SpinLock, 4096>::new()?;
// Allocate an object
let mut item = cache.alloc()?; // Returns SlabBox<MyConfig>
item.id = 1;
item.data[0] = 0xFF;
// Memory is automatically returned to the slab when 'item' is dropped.
Ok(())
}
```
---
## 🏗 Deep Dive: Master-Slave Architecture
1. **Master Slab**: The first slab created by `SlabCache`. It holds the global lock and reference count.
2. **Slave Slabs**: When the Master is full, it requests more memory via your hooks to create a Slave.
3. **Independent Deallocation**: This is the killer feature. Because every slab is aligned to its own size, a `SlabBox` can find its header by simply masking its own address. You can clone the `SlabCache`, drop the original, or move the `SlabBox` to a different thread; it will always find its way home.
---
## ⚠️ Safety & Constraints (Important!)
### 1. The Power-of-Two Rule
The `SLAB_SIZE` constant **must** be a power of two (e.g., 1024, 4096, 65536). This is required for the bitmasking logic that finds the slab header. The library checks this at compile-time.
### 2. Minimum Type Size
Your type `T` must be at least **4 bytes (`u32`)**. When a slot is free, the allocator stores a 32-bit index inside the slot to maintain the free-list. Types smaller than 4 bytes will trigger a compile-time error.
### 3. Maximum Type Size
A single slab must be large enough to fit the `Slab` header plus **at least two slots** of type `T`.
### 4. Lock Size
If you implement a custom `LockTrait`, your lock structure must be **16 bytes or smaller**. This ensures the Slab header remains compact and efficient.
### 5. Memory Corruption
Since this is a low-level allocator:
* **Double Frees**: Manually freeing the same pointer twice will corrupt the internal free-list. **Always use `SlabBox`** to avoid this.
* **Buffer Overflows**: Writing outside the bounds of your type `T` will overwrite slab metadata or other slots, leading to internal panics or silent corruption.
---
## ❌ Error Handling
The library uses a custom `Result` type and `SlabError` enum:
- `OutOfMemory`: The system hooks failed to provide memory, or the slab is at capacity.
- `InvalidPointer`: The "Magic Sentinel" check failed. This usually indicates a use-after-free or that the pointer doesn't belong to a valid slab.
- `AlignmentMismatch`: The pointer address is not correctly aligned for the slab size.
- `FatalError`: Internal logic corruption occurred.
---
## ⚖️ License
Licensed under the **MIT License**. See [LICENSE](LICENSE) for details.
[crate-badge]: https://img.shields.io/crates/v/attachable-slab-allocator.svg
[crate-link]: https://crates.io/crates/attachable-slab-allocator
[docs-image]: https://docs.rs/attachable-slab-allocator/badge.svg
[docs-link]: https://docs.rs/attachable-slab-allocator
[license-image]: https://img.shields.io/badge/MIT-blue.svg
[repo-size]: https://img.shields.io/github/repo-size/KiyanSisakhti/attachable-slab-allocator
[total-lines]: https://aschey.tech/tokei/github/KiyanSisakhti/attachable-slab-allocator
[git-ci]:https://github.com/KiyanSisakhti/attachable-slab-allocator/actions/workflows/rust.yml/badge.svg?branch=main
[license-link]: #license