combarc/lib.rs
1//! # CombArc
2//!
3//! CombArc stands for "clone-on-mutable-borrow automatic reference counter", but it is essentially
4//! a copy-on-write that transparently wraps [`Arc::as_ref`] and [`Arc::make_mut`] around the
5//! [`Deref`] and [`DerefMut`] traits, respectively.
6//!
7//! As such, it has the same effects when borrowed mutably as [`Arc::make_mut`] when called:
8//! * If there are no other references, it borrows normally.
9//! * If there are strong references, it gets cloned.
10//! * If there are no strong references but there are weak references, then all weak references get
11//! dissociated and can no longer upgrade.
12//!
13//! Note that interior mutability (e.g. [`Cell::set`]) won't trigger a clone.
14//!
15//! This crate uses no unsafe code directly and only uses the `alloc` crate. It provides both a
16//! `CombArc` and `CombRc`, the difference being that `CombArc` is atomic and thread-safe,
17//! where `CombRc` is not thread-safe and cannot be moved across threads.
18//!
19//! [`Arc::as_ref`]: alloc::sync::Arc::as_ref
20//! [`Arc::make_mut`]: alloc::sync::Arc::make_mut
21//! [`Deref`]: core::ops::Deref
22//! [`DerefMut`]: core::ops::DerefMut
23//! [`Cell::set`]: core::cell::Cell::set
24//!
25//! ## Examples
26//!
27//! In this example, `CombArc` is used, but `CombRc` can be used interchangeably here.
28//!
29//! ```rust
30//! use combarc::CombArc;
31//! use std::cell::Cell;
32//!
33//! // Both of these will be the same value.
34//! let mut my_value = CombArc::new(Cell::new(false));
35//! let another_value = my_value.clone();
36//! assert_eq!(my_value, another_value);
37//!
38//! // Cell::set uses interior mutability and does not mutably borrow,
39//! // so they still point to the same memory address.
40//! my_value.set(true);
41//! assert_eq!(my_value, another_value);
42//! assert_eq!(my_value.as_ptr(), another_value.as_ptr());
43//!
44//! // get_mut does mutably borrow, thus `my_value` is cloned.
45//! *my_value.get_mut() = false;
46//! assert_ne!(my_value, another_value);
47//!
48//! // Also, if there is only one reference, `my_value` is not cloned.
49//! let address_before = my_value.as_ptr();
50//! *my_value.get_mut() = true;
51//! let address_after = my_value.as_ptr();
52//! assert_eq!(address_before, address_after);
53//!
54//! // Despite not pointing to the same thing, these are equal now.
55//! assert_ne!(my_value.as_ptr(), another_value.as_ptr());
56//! assert_eq!(my_value, another_value);
57//! ```
58#![no_std]
59#![forbid(unsafe_code)]
60#![forbid(dead_code)]
61#![forbid(missing_docs)]
62
63extern crate alloc;
64
65mod arc;
66mod rc;
67
68#[cfg(test)]
69mod test;
70
71pub use arc::CombArc;
72pub use rc::CombRc;