manual_share/lib.rs
1//! This crate provides a set of types to allow better sharing of the original std types like `Box` and `Vec`:
2//!
3//! | original type | share owner | reference type |
4//! | --- | --- | --- |
5//! | [`Box`] | [`SharedBox`] | [`SharedBoxRef`] |
6//! | [`Vec`] | [`SharedVec`] | [`SharedVecRef`] |
7//! | [`Vec`] | [`SharedVecMut`] | [`SharedVecPart`] |
8//!
9//! # Before using
10//! One should consider using built-in types like [`std::sync::Arc`], [`std::rc::Rc`],
11//! or other smart containers like `bytes::Bytes` or `arc-slice::ArcSlice` (which provide similar functionality of [`SharedVec`] and [`SharedVecMut`]).
12//! These types use automatic resource management and are often easier to use.
13//!
14//! Also, sometimes rust built-in borrow checker is enough,
15//! for example, [`std::thread::scope`] can be used to shared values to other threads
16//! using vallina references without any runtime overhead.
17//!
18//! This crate use a "malloc-free" style manual resource management.
19//! The borrowed **reference types** must be returned to the **share owner**,
20//! otherwise a leak will occur,
21//! and the **share owner** can never be converted back to the **original type** (use reference counting to enforce this).
22//!
23//! Users can enable **`panic-on-drop`** feature, so that whenever a leak happens, the thread panics to help users find the problem.
24//!
25//! # Pros
26//! 1. Conversion between the original type and the shared type is copy free,
27//! while conversion between [`std::sync::Arc`] and [`Box`] involves new allocation and copy.
28//! 2. No atomic Read-Modify-Write overhead, because only one thread can modify the reference counting.
29//! 3. Despite the need to sent back the reference to the owner,
30//! in many cases, a `JoinHandle` is provide to easily do that.
31//!
32//!
33//! # Feature flags
34//! - **`panic-on-drop`** (_enabled by default_)
35//! When enabled, dropping **reference types** will panic,
36//! dropping **share owners** will panic when there are references not returned to it.
37//! - **`do-not-panic-when-panicking`** (_enabled by default_)
38//! Prevent panic-on-drop when the thread is already panicking.
39//! This can prevent too much unrelated information being printed out when the thread is panicking due to other reasons.
40//!
41//!
42//! # Special ZST handling
43//! ZST (Zero-Sized Types) are types that have no size, such as `()` or `struct {}`.
44//! ZST allocated on heap can have the same address,
45//! so the ptr equallity check of returning methods such as [`SharedBox::try_return`]
46//! can't tell whether the [`SharedBoxRef`] has the same origin,
47//! allowing [`SharedBoxRef`] created by one [`SharedBox`] to be returned to a different [`SharedBox`].
48//!
49//! This is totally fine in the sense that ZST has no data and do points to the same address.
50//! However, this allows returning more [`SharedBoxRef`] than what the original [`SharedBox`] has created,
51//! which will underflow the borrow count.
52//!
53//! So an underflow check is added for ZST,
54//! giving back more [`SharedBoxRef`] will return an `Err` containing the [`SharedBoxRef`].
55//!
56//! User should be aware of the two difference of ZST compared to non-ZSTs:
57//! 1. [`SharedBoxRef`] created by one [`SharedBox`] can be returned to a different [`SharedBox`],
58//! which is not allowed for non-ZSTs.
59//! 2. Giving back more [`SharedBoxRef`] than what the original [`SharedBox`] has created will return an `Err` containing the [`SharedBoxRef`].
60//!
61//! The above model for handling ZST originated from discussions in
62//! [a post in Rust user forum](https://users.rust-lang.org/t/built-a-crate-to-safely-share-box-and-vec-manually/141138/5).
63
64pub mod shared_box;
65pub mod shared_vec;
66pub use shared_box::*;
67pub use shared_vec::*;