1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
//! # CDPT: Concurrent Deferred Partial Tracing
//!
//! An automatic, safe, and concurrent garbage collector for building lock-free
//! and concurrent data structures in Rust, with **no `unsafe`**, **no
//! stop-the-world pauses**, and **automatic reclamation of cyclic garbage**.
//!
//! CDPT is a *partial-tracing* collector: it reference-counts only the roots
//! and traces the rest of the heap. This makes it safe (the roots are precise,
//! and a type-safe API rules out use-after-free and leaks at compile time) and
//! easy to use (tracing reclaims cycles for you). A highly concurrent design
//! keeps it efficient: tracing runs alongside your threads without ever
//! suspending them, and deferred reference counting amortizes the root-count
//! updates, so traversals touch no counts at all. For the algorithm and its
//! correctness, see the [paper](https://doi.org/10.1145/3808310).
//!
//! ## Quick start
//!
//! ```
//! use cdpt::*;
//!
//! #[derive(TraceObj)]
//! struct Node {
//! value: usize,
//! next: AtomicSharedOption<Node>,
//! }
//!
//! // Pin the current thread to access the managed heap.
//! let handle = handle();
//! let guard = handle.pin();
//!
//! // Allocate and dereference while the guard is alive.
//! let node = Local::new(Node { value: 42, next: AtomicSharedOption::none() }, &guard);
//! assert_eq!(node.value, 42); // `Local` dereferences to `&T`
//!
//! // Promote to references that outlive the guard.
//! let kept = node.protect(&handle); // `Local<Handle, Node>`: cheap, this thread only
//! let shared = node.as_shared(); // `Shared<Node>`: root-counted, like `Arc`
//!
//! drop(guard); // the collector can now make progress
//!
//! assert_eq!(kept.value, 42); // still valid
//! let alias = shared.clone(); // `Shared` is `Clone` + `Send + Sync`
//! assert_eq!(alias.value, 42); // still valid
//! ```
//!
//! ## Core concepts
//!
//! **The managed heap.** CDPT manages a dedicated heap of *managed objects*:
//! values you allocate through CDPT's pointer types instead of `Box` or `Arc`.
//! Only objects you allocate this way are collected; the rest of your program
//! is left untouched.
//!
//! **Guards.** To touch the managed heap (allocate a managed object or load an
//! atomic pointer), a thread must hold a [`Guard`], obtained with [`pin()`] or
//! [`Handle::pin`]. A guard is **not a lock**: any number of threads may hold
//! their own guards at once. It simply marks the thread as actively using the
//! heap, so the collector knows not to reclaim anything the thread might still
//! reach. While a guard is alive, every pointer you load is safe to
//! dereference.
//!
//! **Keep guards short-lived.** A live guard holds the collector back. Pin, do
//! your work, and drop the guard promptly, ideally one short critical section
//! per operation. Avoid holding a guard across blocking calls or long loops; if
//! you must, refresh it periodically with [`Guard::repin`].
//!
//! **Promotion.** A [`Local`] loaded under a guard is valid only until that
//! guard drops. To keep a reference past the guard, *promote* it: to a
//! [`Local<Handle, T>`](Local) via [`Local::protect`] (cheap, hazard-pointer
//! protection) or to a [`Shared<T>`](Shared) via [`Local::as_shared`] (sendable
//! across threads). You can then drop the guard and keep using the reference.
//!
//! **What keeps an object alive.** An object survives as long as it is
//! *reachable*: held by a live [`Shared`] or a promoted [`Local`], or pointed
//! to (transitively) from another live object. Once the last such reference is
//! gone, the collector reclaims it, including whole cycles of objects that
//! only reference each other.
//!
//! ## The pointer types
//!
//! Four types cover every role:
//!
//! | Type | Nullable | Lifetime | Deref | `Send` |
//! |------|----------|----------|-------|--------|
//! | [`Local<Guard, T>`](Local) | No | Scoped to its [`Guard`] | Yes | No |
//! | [`Local<Handle, T>`](Local) | No | Until dropped | Yes | No |
//! | [`Shared<T>`](Shared) | No | Until dropped | Yes | Yes |
//! | [`AtomicShared<T>`](AtomicShared) | No | Until dropped | No (load first) | Yes |
//! | [`AtomicSharedOption<T>`](AtomicSharedOption) | Yes | Until dropped | No (load first) | Yes |
//!
//! - **[`Local`]** is the uncounted reference you hold while traversing the heap;
//! it dereferences to `&T`. It comes in two flavors: `Local<Guard, T>`
//! (zero-cost, `Copy`, valid for the guard's scope) and `Local<Handle, T>`
//! (hazard-pointer protected, outlives the guard).
//! - **[`Shared`]** is an immutable, sendable, long-lived reference: the GC's
//! `Arc<T>`. Clone it to share; store it as a struct field for an immutable
//! heap edge.
//! - **[`AtomicShared`] / [`AtomicSharedOption`]** are the *mutable* edges
//! inside your data structure (non-nullable / nullable). Their `load`,
//! `store`, `swap`, and `compare_exchange` apply the GC's write barriers for
//! you.
//!
//! You move between them along a few simple paths:
//!
//! - `AtomicShared*::load(.., &guard)` → `Local<Guard, T>`
//! - [`Local::protect`]`(&handle)` → `Local<Handle, T>` (outlives the guard)
//! - [`Local::as_shared`]`()` → [`Shared<T>`](Shared) (sendable, root-counted)
//! - [`Shared::as_local`]`(&guard)` → `Local<Guard, T>`
//!
//! ## Building data structures
//!
//! 1. **Derive [`TraceObj`](trait@TraceObj)** on every managed type. The
//! `#[derive(TraceObj)]` macro finds the managed-pointer fields (including
//! those nested in `Option`, `Vec`, `Box`, tuples, …) and generates the
//! tracing code automatically.
//! 2. **Use `Atomic*` for edges that mutate**, and [`Shared`] for immutable
//! ones. The example below links nodes immutably with [`Shared`]:
//!
//! ```
//! use cdpt::*;
//!
//! #[derive(TraceObj)]
//! struct Tree {
//! value: i32,
//! children: Vec<Shared<Tree>>,
//! }
//!
//! let guard = pin();
//! let leaf = Shared::new(Tree { value: 1, children: vec![] }, &guard);
//! let root = Shared::new(Tree { value: 2, children: vec![leaf.clone()] }, &guard);
//! drop(guard);
//!
//! // `root` keeps itself alive; `leaf` stays alive as `root`'s child.
//! assert_eq!(root.value, 2);
//! assert_eq!(root.children[0].value, 1);
//! ```
//!
//! 3. **Read and update edges with the usual atomic operations.** `load`,
//! `store`, `swap`, and `compare_exchange` mirror `AtomicPtr` and crossbeam's
//! `Atomic`, so the lock-free traversal and update patterns you already know
//! carry over unchanged. Two things are specific to CDPT:
//! - Every operation takes a `&guard`, and `load` hands back a [`Local`]
//! *without* touching a reference count, so traversal stays cheap.
//! - A loaded [`Local`] is valid only while the guard lives. To use it after
//! the guard drops (return it, store it, or send it to another thread),
//! promote it with [`Local::protect`] or [`Local::as_shared`].
//!
//! **Things to keep in mind:**
//!
//! - Keep guards short-lived (see [Core concepts](#core-concepts)).
//! - Managed types are `Send + Sync` (required by [`TraceObj`](trait@TraceObj)).
//!
//! See the `examples/` directory for complete lock-free structures: a Treiber
//! stack, a Harris linked list, and the Natarajan–Mittal and Ellen et al.
//! (EFRB) trees.
//!
//! ## Configuration and tuning
//!
//! Collection runs automatically, so most programs need nothing here. For
//! control, [`global()`] returns the [`Global`] singleton:
//!
//! - [`Global::enable_collection`]: pause or resume collection.
//! - [`Global::request_collection`]: force a cycle now (useful in tests).
//! - [`Global::set_heap_headroom`] / [`HeapHeadroom`]: trade peak memory
//! against collector CPU.
//! - [`Global::set_collector_threads`]: set the collector's parallelism.
//! - [`Global::estimate_heap_usage`] and friends: coarse heap statistics.
//!
//! Cargo features:
//!
//! - `tag`: low-bit pointer tagging (the `*_with_tag` and `fetch_tag_*` APIs),
//! for lock-free algorithms that mark pointers.
//!
//! ## Limitations and requirements
//!
//! - **No finalizers.** When an object is reclaimed its fields are dropped
//! normally, but you cannot run custom `Drop` logic on a managed type. The
//! derive supplies the destructor, and reclamation timing is not observable.
//! - **No unboxing.** Once a managed object becomes a heap edge of another
//! object, it cannot be moved back onto the stack. The API enforces this:
//! [`Local`] and [`Shared`] dereference to `&T` only.
//! - **`Send + Sync` required.** Managed objects are shared with other threads
//! and the collector, so any interior-mutable state must use a thread-safe
//! primitive (`Mutex`, atomics, …).
//! - **Memory overhead.** Tracing keeps garbage until the next cycle confirms
//! it dead, and every object carries a small header. Expect a higher
//! footprint than hand-tuned manual reclamation, in exchange for safety and
//! automatic cycle collection.
//!
//! ## Further reading
//!
//! - The [paper](https://doi.org/10.1145/3808310): design, correctness, and
//! evaluation against `Arc`, BDWGC, CIRC, and manual schemes.
//! - `README.md`: project overview and a feature comparison.
//! - `BENCH.md`: running the benchmark suite.
//! - `examples/`: complete lock-free data structures.
extern crate static_assertions;
pub use TraceObj;
pub use ;
pub use ;
pub use ;
pub use *;