Skip to main content

attachable_slab_allocator/
lib.rs

1//! # Attachable Slab Allocator: The Manual 🦀
2//!
3//! A high-performance, $O(1)$, Master-Slave slab allocator designed for `no_std` environments,
4//! kernels, and embedded systems.
5//!
6//! ## 1. The Core Philosophy: "The Bridge"
7//!
8//! This library provides the logic for dividing memory into fixed-size "slots", but it does
9//! not know how to acquire raw memory from the system. You must provide two "bridges"
10//! (hooks) using the `define_allocation_hooks!` macro.
11//!
12//! **Note:** If these hooks are not defined, your code will fail to link.
13//!
14//! ### Example: Setting up Hooks
15//! ```rust, ignore
16//! use std::alloc::{alloc, dealloc, Layout};
17//! use core::ptr::NonNull;
18//! use attachable_slab_allocator::{define_allocation_hooks, Result};
19//!
20//! unsafe fn my_alloc(layout: Layout) -> Option<NonNull<u8>> {
21//!     NonNull::new(alloc(layout))
22//! }
23//!
24//! unsafe fn my_free(ptr: NonNull<u8>, layout: Layout) -> Result<()> {
25//!     dealloc(ptr.as_ptr(), layout);
26//!     Ok(())
27//! }
28//!
29//! define_allocation_hooks!(my_alloc, my_free);
30//! ```
31//!
32//! ## 2. Using `SlabCache`
33//!
34//! `SlabCache` is the primary interface. It is reference-counted and handles the
35//! creation of Slaves when memory runs out.
36//!
37//! ### Constraints on `T` and `SLAB_SIZE`:
38//! - **`T` Size**: Must be at least 4 bytes (`u32`) to store internal freelist indices.
39//! - **`T` Alignment**: Must be at least `u32` aligned.
40//! - **`SLAB_SIZE`**: Must be a **Power of Two**.
41//! - **Slab Alignment**: The allocator enforces that `Slab Alignment == SLAB_SIZE`. This is
42//!   checked at compile time.
43//!
44//! ### Example: Allocation
45//! ```rust, ignore
46//! use attachable_slab_allocator::{SlabCache, locks::SpinLock};
47//!
48//! // Create a cache for u64, using a 4096-byte slab size.
49//! let mut cache = SlabCache::<u64, SpinLock, 4096>::new().unwrap();
50//!
51//! // Allocate a smart pointer (SlabBox)
52//! let mut boxed_val = cache.alloc().unwrap();
53//! *boxed_val = 12345;
54//!
55//! // boxed_val is dropped here, returning memory to the slab automatically.
56//! ```
57//!
58//! ## 3. Synchronization and Locks
59//!
60//! The allocator uses a **Master-Slave** architecture. The **Master Slab** holds the
61//! lock that protects the entire hierarchy (itself and all its Slaves).
62//!
63//! ### Custom Locks:
64//! You can implement the `LockTrait` for your own synchronization primitive.
65//! **Requirement**: The lock structure must be **smaller than or equal to 16 bytes**
66//! to ensure the slab header remains efficient.
67//!
68//! ## 4. `SlabBox`: Independence & RAII
69//!
70//! `SlabBox<T>` is a smart pointer that automatically returns its memory to the slab
71//! when dropped. It is **independent** of the `SlabCache`. You can clone the cache,
72//! drop the cache, or move the `SlabBox` to another thread—it will always find its
73//! home slab using the "Alignment == Size" bitmask trick.
74//!
75//! ## 5. Internal Mechanisms
76//!
77//! - **Link Lists**: The allocator uses internal intrusive doubly linked lists to
78//!   manage slabs. Metadata is stored *inside* the slab headers.
79//! - **Freelist**: Within each slab, free slots are tracked using an intrusive
80//!   stack (the slot memory itself stores the index of the next free slot).
81//!
82//! ## 6. Error Handling and Safety
83//!
84//! ### `Result` and `SlabError`:
85//! Operations return a `Result<T, SlabError>`. Common errors include:
86//! - `OutOfMemory`: System hooks failed or capacity reached.
87//! - `InvalidPointer`: Magic header check failed (indicates corruption or use-after-free).
88//!
89//! ### ⚠️ Critical Safety:
90//! - **Internal Panic/Corruption**: If you write outside the bounds of your type `T`,
91//!   you might overwrite the `Slab` header or the internal freelist. This can lead to
92//!   internal panics or silent data corruption.
93//! - **Double Free**: Manually freeing the same pointer twice will corrupt the
94//!   internal list. Always prefer `SlabBox` for automatic management.
95
96#![no_std]
97
98mod allocation;
99mod defs;
100mod mem_lay;
101mod slab;
102mod slab_box;
103mod slab_cache;
104mod slots;
105mod utils;
106
107pub mod locks;
108#[doc(inline)]
109pub use defs::Result;
110#[doc(inline)]
111pub use defs::SlabError;
112#[doc(inline)]
113pub use slab_box::SlabBox;
114#[doc(inline)]
115pub use slab_cache::SlabCache;
116
117mod prelude {
118    pub use crate::allocation::*;
119    pub use crate::defs::*;
120    pub use crate::utils::*;
121}