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
//! This crate provides a set (eventually) of smart pointer types that
//! allow read access with no guards (and minimal to no overhead) and
//! no need to call [std::borrow::Borrow]. These smart pointers each
//! allow internal mutability (obtaining mutable references) by a
//! Read-Copy-Update approach, so you get a mutable reference to a
//! private copy of the data, which you can mutate at will. When the
//! mutation is complete the pointer is atomically updated. Old
//! references to the data may still exist, and will still be a valid
//! reference to the old data.
//!
//! Basically, these smart pointers allow internal mutability through
//! a slow and painful process, while keeping read-only access both
//! fast and easy (in particular, no need to call `ptr.borrow()`
//! everywhere). Write access is guarded, but read access is not.
//!
//! The names of the types are based on the standard smart pointer
//! types.
//!
//! 1. `[BoxRcu]` is an owned pointer similar to [std::box::Box]. If
//! you like, it is actually closer to `Box<RefCell<T>>`, or even
//! `Box<Mutex<T>>`, but without the nuisance of having to call
//! borrow when reading.
//!
//! 2. `[RcRcu]` is a reference counted pointer similar to [std::rc::Rc].
//! If you like, it is actually closer to `Rc<RefCell<T>>`, but
//! without the nuisance of having to call borrow when reading.
//!
//! 3. `ArcRcu` is planned to be a thread-safe reference counted
//! pointer similar to [std::sync::Arc]. It is actually
//! closer to `Arc<RwLock<T>>`, but without the nuisance of having to
//! call `read` before reading.
//!
//! ### Cleaning
//!
//! Due to this crate's read-copy-update semantics, old copies of your
//! data are kept until we are confident that there are no longer any
//! references to them. Because we do not have any guards on the read
//! references, this must be done manually. This is the cost we pay
//! for extra convenience (and much improved read speed in the case of
//! `ArcRcu`) on the read operations. You have two options for how to
//! handle this.
//!
//! One option is to simply store those extra copies until then entire
//! smart pointer itself is freed. That is what happens if you do
//! nothing, and for small data that is only mutated once, it's a fine
//! option. However, for `[ArcRcu]` and `[RcRcu]` there will be a
//! slowdown on reading until you do call clean, since an extra level
//! of pointer redirection will be required.
//!
//! The other option is to call `clean()` when convenient. `clean`
//! takes a `&mut self`, so when it is called, the compiler will prove
//! to us that there are no other references out there via *this*
//! smart pointer. For `BoxCell` that is sufficient to prove that we
//! can free the data. In the case of the reference counted data
//! pointers, we keep track of a count of how many copies have been
//! dereferenced since the last time `clean` was called. We could
//! probably be more accurate with "epoch" tracking, but I don't know
//! that the complexity will be worthwhile.
pub use crateBoxRcu;
pub use crateRcRcu;
pub use crateArcRcu;
impl_stuff!;
impl_stuff!;
impl_stuff!;