rclite/lib.rs
1#![no_std]
2//! # RcLite: small, fast, and memory-friendly reference counting
3//!
4//! [![Crates.io][crates-badge]][crates-url]
5//! [![Documentation][doc-badge]][doc-url]
6//! [![MIT licensed][mit-badge]][mit-url]
7//! [![Apache 2 licensed][apache-badge]][apache-url]
8//!
9//! [crates-badge]: https://img.shields.io/crates/v/rclite.svg?style=for-the-badge
10//! [crates-url]: https://crates.io/crates/rclite
11//! [mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg?style=for-the-badge
12//! [apache-badge]: https://img.shields.io/badge/license-Apache2-orange.svg?style=for-the-badge
13//! [mit-url]: https://github.com/fereidani/rclite/blob/master/LICENSE-MIT
14//! [apache-url]: https://github.com/fereidani/rclite/blob/master/LICENSE-APACHE
15//! [doc-badge]: https://img.shields.io/docsrs/rclite?style=for-the-badge
16//! [doc-url]: https://docs.rs/rclite
17//!
18//! RcLite is a lightweight reference-counting solution for Rust that serves as
19//! an alternative to the standard library's reference-counting. It offers both
20//! multi-threaded and single-threaded reference counting options with improved
21//! performance and reduced memory overhead, boasting at least 50% and up to
22//! 100% decrease in memory overhead compared to the standard library reference
23//! counting. RcLite is a suitable option when weak references are not necessary
24//! and optimizing for performance and memory usage is a priority.
25//!
26//! ## Why use RcLite?
27//!
28//! - It's faster and smaller
29//! - Uses less memory
30//! - It provides a lightweight drop-in replacements for standard library
31//! `std::sync::Arc` and `std::rc::Rc`
32//! - It supports `no_std` with extern alloc
33//!
34//! ## Why not use RcLite?
35//!
36//! - It does not provide weak references
37//! - It does not support data as DSTs
38//! - With RcLite in 64-bit systems, you only can have `4,294,967,296 - 256`
39//! live references to an object which requires about 32GBs of ram for holding
40//! all these references to this single object location. if you need to have
41//! `18,446,744,073,709,551,616` live references to an object, use the
42//! standard library. In other systems with smaller pointer sizes like 32-bit,
43//! you will have `usize::MAX` live references limitation that is the same as
44//! the standard library.
45//!
46//! ## Comparison
47//!
48//! | | rclite::{Arc,Rc} | std::\*::{Arc,Rc} |
49//! | -------------------------- | :--------------: | :---------------: |
50//! | Overhead in 64-bit systems | 4 bytes | 16 bytes |
51//! | Overhead in 32-bit systems | 4 or 2 bytes | 8 bytes |
52//! | Overhead in 16-bit systems | 2 or 1 bytes | 4 bytes |
53//! | Weak References | ❌ | ✅ |
54//! | DST Support | ❌ | ✅ |
55//!
56//! In 64-bit systems, RcLite has an advantage over the standard library's Arc
57//! as it can utilize the memory padding area, using only 4 bytes to store the
58//! counter. This results in a reduction in memory usage, as there is less
59//! memory waste on padding. However, in situations where there is not enough
60//! padding available in the structure, RcLite will have an overhead of 8 bytes,
61//! which is still half of the standard library's overhead.
62//!
63//! For instance, in 64-bit systems, `Rc<u32>` and `Arc<u32>` allocate the same
64//! amount of memory as `Box<u32>`, since the `Box<u32>` allocation will be
65//! padded to `u64` by the allocator.
66//!
67//! In 32-bit and 16-bit systems, the memory overhead of the RcLite will be 50%
68//! of the standard library.
69//!
70//! ### Features
71//!
72//! By default, RcLite uses a counter size of half the word size for 64-bit
73//! systems, with the `usize-for-small-platforms` feature enabled. This is
74//! because overflowing a 32-bit counter is harder compared to overflowing
75//! 16-bit counters. If you wish to use the half register size on other
76//! platforms, you can disable the default features by setting
77//! `default-features = false`. This will result in the use of 16-bit counters
78//! on 32-bit platforms and 8-bit counters on 16-bit platforms.
79
80#![warn(missing_docs, missing_debug_implementations)]
81extern crate alloc;
82
83// Arc counter definition
84
85#[cfg(target_pointer_width = "64")]
86pub(crate) use core::sync::atomic::AtomicU32 as AtomicCounter;
87
88#[cfg(all(
89 not(target_pointer_width = "64"),
90 not(target_pointer_width = "16"),
91 feature = "usize-for-small-platforms",
92))]
93pub(crate) use core::sync::atomic::AtomicUsize as AtomicCounter;
94
95#[cfg(all(
96 target_pointer_width = "32",
97 not(feature = "usize-for-small-platforms")
98))]
99pub(crate) use core::sync::atomic::AtomicU16 as AtomicCounter;
100
101// Rc counter definition
102
103#[cfg(target_pointer_width = "64")]
104pub(crate) use u32 as ucount;
105
106#[cfg(all(
107 not(target_pointer_width = "64"),
108 feature = "usize-for-small-platforms"
109))]
110pub(crate) use usize as ucount;
111
112#[cfg(all(
113 target_pointer_width = "32",
114 not(feature = "usize-for-small-platforms")
115))]
116pub(crate) use u16 as ucount;
117
118#[cfg(all(
119 target_pointer_width = "16",
120 not(feature = "usize-for-small-platforms")
121))]
122pub(crate) use u8 as ucount;
123
124#[cfg(all(not(target_pointer_width = "16")))]
125mod arc;
126mod rc;
127#[cfg(all(not(target_pointer_width = "16")))]
128pub use arc::*;
129pub use rc::*;