ring_alloc/
lib.rs

1#![doc = include_str!("../README.md")]
2#![cfg_attr(not(feature = "std"), no_std)]
3#![cfg_attr(feature = "nightly", feature(allocator_api))]
4#![warn(unsafe_op_in_unsafe_fn)]
5
6#[cfg(feature = "alloc")]
7extern crate alloc;
8
9mod chunk;
10mod local;
11
12#[cfg(feature = "std")]
13mod global;
14
15use core::{alloc::Layout, cell::Cell, sync::atomic::Ordering};
16
17pub use self::local::RingAlloc;
18
19#[cfg(feature = "std")]
20pub use self::global::OneRingAlloc;
21
22#[allow(clippy::transmutes_expressible_as_ptr_casts)]
23fn addr<T: ?Sized>(ptr: *const T) -> usize {
24    // Safety: pointer to address conversion is always valid.
25    unsafe { core::mem::transmute(ptr.cast::<()>()) }
26}
27
28/// # Safety
29///
30/// New address must be withing same allocation as `ptr`.
31/// Address must be aligned for `T`.
32/// `addr` must be non-zero.
33unsafe fn with_addr_mut<T>(ptr: *mut T, dest_addr: usize) -> *mut T {
34    let ptr_addr = addr(ptr) as isize;
35    let offset = (dest_addr as isize).wrapping_sub(ptr_addr);
36    ptr.cast::<u8>().wrapping_offset(offset).cast()
37}
38
39trait ImUsize {
40    fn new(value: usize) -> Self;
41    fn load(&self, ordering: Ordering) -> usize;
42    fn store(&self, value: usize, ordering: Ordering);
43    fn fetch_add(&self, value: usize, ordering: Ordering) -> usize;
44}
45
46impl ImUsize for Cell<usize> {
47    #[inline(always)]
48    fn new(value: usize) -> Self {
49        Cell::new(value)
50    }
51
52    #[inline(always)]
53    fn load(&self, _ordering: Ordering) -> usize {
54        self.get()
55    }
56
57    #[inline(always)]
58    fn store(&self, value: usize, _ordering: Ordering) {
59        self.set(value)
60    }
61
62    #[inline(always)]
63    fn fetch_add(&self, value: usize, _ordering: Ordering) -> usize {
64        let old_value = self.get();
65        self.set(old_value.wrapping_add(value));
66        old_value
67    }
68}
69
70#[cfg(feature = "std")]
71impl ImUsize for core::sync::atomic::AtomicUsize {
72    #[inline(always)]
73    fn new(value: usize) -> Self {
74        Self::new(value)
75    }
76
77    #[inline(always)]
78    fn load(&self, ordering: Ordering) -> usize {
79        self.load(ordering)
80    }
81
82    #[inline(always)]
83    fn store(&self, value: usize, ordering: Ordering) {
84        self.store(value, ordering)
85    }
86
87    #[inline(always)]
88    fn fetch_add(&self, value: usize, ordering: Ordering) -> usize {
89        self.fetch_add(value, ordering)
90    }
91}
92
93#[inline(always)]
94fn layout_max(layout: Layout) -> usize {
95    layout.align().max(layout.size())
96}
97
98#[inline(always)]
99#[cold]
100fn cold() {}
101
102#[cfg(test)]
103mod tests;