• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 Amanieu d'Antras
2 // Copyright 2020 Amari Robinson
3 //
4 // Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
5 // http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
6 // http://opensource.org/licenses/MIT>, at your option. This file may not be
7 // copied, modified, or distributed except according to those terms.
8 
9 //! Intrusive collections for Rust.
10 //!
11 //! This library provides a set of high-performance intrusive collections which
12 //! can offer better performance and more flexibility than standard collections.
13 //!
14 //! The main difference between an intrusive collection and a normal one is that
15 //! while normal collections allocate memory behind your back to keep track of a
16 //! set of *values*, intrusive collections never allocate memory themselves and
17 //! instead keep track of a set of *objects*. Such collections are called
18 //! intrusive because they requires explicit support in objects to allow them to
19 //! be inserted into a collection.
20 //!
21 //! # Example
22 //!
23 //! ```
24 //! use intrusive_collections::intrusive_adapter;
25 //! use intrusive_collections::{LinkedList, LinkedListLink};
26 //! use std::cell::Cell;
27 //!
28 //! // A simple struct containing an instrusive link and a value
29 //! struct Test {
30 //!     link: LinkedListLink,
31 //!     value: Cell<i32>,
32 //! }
33 //!
34 //! // The adapter describes how an object can be inserted into an intrusive
35 //! // collection. This is automatically generated using a macro.
36 //! intrusive_adapter!(TestAdapter = Box<Test>: Test { link: LinkedListLink });
37 //!
38 //! // Create a list and some objects
39 //! let mut list = LinkedList::new(TestAdapter::new());
40 //! let a = Box::new(Test {
41 //!     link: LinkedListLink::new(),
42 //!     value: Cell::new(1),
43 //! });
44 //! let b = Box::new(Test {
45 //!     link: LinkedListLink::new(),
46 //!     value: Cell::new(2),
47 //! });
48 //! let c = Box::new(Test {
49 //!     link: LinkedListLink::new(),
50 //!     value: Cell::new(3),
51 //! });
52 //!
53 //! // Insert the objects at the front of the list
54 //! list.push_front(a);
55 //! list.push_front(b);
56 //! list.push_front(c);
57 //! assert_eq!(list.iter().map(|x| x.value.get()).collect::<Vec<_>>(), [3, 2, 1]);
58 //!
59 //! // At this point, the objects are owned by the list, and we can modify
60 //! // them through the list.
61 //! list.front().get().unwrap().value.set(4);
62 //! assert_eq!(list.iter().map(|x| x.value.get()).collect::<Vec<_>>(), [4, 2, 1]);
63 //!
64 //! // Removing an object from an instrusive collection gives us back the
65 //! // Box<Test> that we originally inserted into it.
66 //! let a = list.pop_front().unwrap();
67 //! assert_eq!(a.value.get(), 4);
68 //! assert_eq!(list.iter().map(|x| x.value.get()).collect::<Vec<_>>(), [2, 1]);
69 //!
70 //! // Dropping the collection will automatically free b and c by
71 //! // transforming them back into Box<Test> and dropping them.
72 //! drop(list);
73 //! ```
74 //!
75 //! # Links and adapters
76 //!
77 //! Intrusive collections track objects through links which are embedded within
78 //! the objects themselves. It also allows a single object to be part of
79 //! multiple intrusive collections at once by having multiple links in it.
80 //!
81 //! The relationship between an object and a link inside it is described by the
82 //! `Adapter` trait. Intrusive collections use an implementation of this trait
83 //! to determine which link in an object should be used by the collection. In
84 //! most cases you do not need to write an implementation manually: the
85 //! `intrusive_adapter!` macro will automatically generate the necessary code.
86 //!
87 //! For red-black trees, the adapter must also implement the `KeyAdapter` trait
88 //! which allows a key to be extracted from an object. This key is then used to
89 //! keep all elements in the tree in ascending order.
90 //!
91 //! ```
92 //! use intrusive_collections::intrusive_adapter;
93 //! use intrusive_collections::{SinglyLinkedListLink, SinglyLinkedList};
94 //! use intrusive_collections::{LinkedListLink, LinkedList};
95 //! use intrusive_collections::{XorLinkedList, XorLinkedListLink};
96 //! use intrusive_collections::{RBTreeLink, RBTree, KeyAdapter};
97 //! use std::rc::Rc;
98 //!
99 //! // This struct can be inside three lists and one tree simultaneously
100 //! #[derive(Default)]
101 //! struct Test {
102 //!     link: LinkedListLink,
103 //!     link2: SinglyLinkedListLink,
104 //!     link3: XorLinkedListLink,
105 //!     link4: RBTreeLink,
106 //!     value: i32,
107 //! }
108 //!
109 //! intrusive_adapter!(MyAdapter = Rc<Test>: Test { link: LinkedListLink });
110 //! intrusive_adapter!(MyAdapter2 = Rc<Test>: Test { link2: SinglyLinkedListLink });
111 //! intrusive_adapter!(MyAdapter3 = Rc<Test>: Test { link3: XorLinkedListLink });
112 //! intrusive_adapter!(MyAdapter4 = Rc<Test>: Test { link4: RBTreeLink });
113 //! impl<'a> KeyAdapter<'a> for MyAdapter4 {
114 //!     type Key = i32;
115 //!     fn get_key(&self, x: &'a Test) -> i32 { x.value }
116 //! }
117 //!
118 //! let mut a = LinkedList::new(MyAdapter::new());
119 //! let mut b = SinglyLinkedList::new(MyAdapter2::new());
120 //! let mut c = XorLinkedList::new(MyAdapter3::new());
121 //! let mut d = RBTree::new(MyAdapter4::new());
122 //!
123 //! let test = Rc::new(Test::default());
124 //! a.push_front(test.clone());
125 //! b.push_front(test.clone());
126 //! c.push_front(test.clone());
127 //! d.insert(test);
128 //! ```
129 //!
130 //! # Cursors
131 //!
132 //! Intrusive collections are manipulated using cursors. A cursor is similar to
133 //! an iterator, except that it can freely seek back-and-forth, and can safely
134 //! mutate the list during iteration. This is similar to how a C++ iterator
135 //! works.
136 //!
137 //! A cursor views an intrusive collection as a circular list, with a special
138 //! null object between the last and first elements of the collection. A cursor
139 //! will either point to a valid object in the collection or to this special
140 //! null object.
141 //!
142 //! Cursors come in two forms: `Cursor` and `CursorMut`. A `Cursor` gives a
143 //! read-only view of a collection, but you are allowed to use multiple `Cursor`
144 //! objects simultaneously on the same collection. On the other hand,
145 //! `CursorMut` can be used to mutate the collection, but you may only use one
146 //! of them at a time.
147 //!
148 //! Cursors are a very powerful abstraction since they allow a collection to be
149 //! mutated safely while it is being iterated on. For example, here is a
150 //! function which removes all values within a given range from a `RBTree`:
151 //!
152 //! ```
153 //! use intrusive_collections::intrusive_adapter;
154 //! use intrusive_collections::{RBTreeLink, RBTree, KeyAdapter, Bound};
155 //!
156 //! struct Element {
157 //!     link: RBTreeLink,
158 //!     value: i32,
159 //! }
160 //!
161 //! intrusive_adapter!(ElementAdapter = Box<Element>: Element { link: RBTreeLink });
162 //! impl<'a> KeyAdapter<'a> for ElementAdapter {
163 //!     type Key = i32;
164 //!     fn get_key(&self, e: &'a Element) -> i32 { e.value }
165 //! }
166 //!
167 //! fn remove_range(tree: &mut RBTree<ElementAdapter>, min: i32, max: i32) {
168 //!     // Find the first element which is greater than or equal to min
169 //!     let mut cursor = tree.lower_bound_mut(Bound::Included(&min));
170 //!
171 //!     // Iterate over all elements in the range [min, max]
172 //!     while cursor.get().map_or(false, |e| e.value <= max) {
173 //!         // CursorMut::remove will return a Some(<Box<Element>), which we
174 //!         // simply drop here. This will also advance the cursor to the next
175 //!         // element.
176 //!         cursor.remove();
177 //!     }
178 //! }
179 //! ```
180 //!
181 //! # Scoped collections
182 //!
183 //! Instead of taking ownership of objects inserted into them, intrusive
184 //! collections can also work with borrowed values. This works by using
185 //! lifetimes and the borrow checker to ensure that any objects inserted into an
186 //! intrusive collection will outlive the collection itself.
187 //!
188 //! ```
189 //! use intrusive_collections::intrusive_adapter;
190 //! use intrusive_collections::{LinkedListLink, LinkedList};
191 //! use typed_arena::Arena;
192 //! use std::cell::Cell;
193 //!
194 //! struct Value {
195 //!     link: LinkedListLink,
196 //!     value: Cell<i32>,
197 //! }
198 //!
199 //! // Note that we use a plain reference as the pointer type for the collection.
200 //! intrusive_adapter!(ValueAdapter<'a> = &'a Value: Value { link: LinkedListLink });
201 //!
202 //! // Create an arena and a list. Note that since stack objects are dropped in
203 //! // reverse order, the Arena must be created before the LinkedList. This
204 //! // ensures that the list is dropped before the values are freed by the
205 //! // arena. This is enforced by the Rust lifetime system.
206 //! let arena = Arena::new();
207 //! let mut list = LinkedList::new(ValueAdapter::new());
208 //!
209 //! // We can now insert values allocated from the arena into the linked list
210 //! list.push_back(arena.alloc(Value {
211 //!     link: LinkedListLink::new(),
212 //!     value: Cell::new(1),
213 //! }));
214 //! list.push_back(arena.alloc(Value {
215 //!     link: LinkedListLink::new(),
216 //!     value: Cell::new(2),
217 //! }));
218 //! list.push_back(arena.alloc(Value {
219 //!     link: LinkedListLink::new(),
220 //!     value: Cell::new(3),
221 //! }));
222 //! assert_eq!(list.iter().map(|x| x.value.get()).collect::<Vec<_>>(), [1, 2, 3]);
223 //!
224 //! // We can also insert stack allocated values into an intrusive list.
225 //! // Again, the values must outlive the LinkedList.
226 //! let a = Value {
227 //!     link: LinkedListLink::new(),
228 //!     value: Cell::new(4),
229 //! };
230 //! let b = Value {
231 //!     link: LinkedListLink::new(),
232 //!     value: Cell::new(5),
233 //! };
234 //! let c = Value {
235 //!     link: LinkedListLink::new(),
236 //!     value: Cell::new(6),
237 //! };
238 //! let mut list2 = LinkedList::new(ValueAdapter::new());
239 //! list2.push_back(&a);
240 //! list2.push_back(&b);
241 //! list2.push_back(&c);
242 //! assert_eq!(list2.iter().map(|x| x.value.get()).collect::<Vec<_>>(), [4, 5, 6]);
243 //!
244 //! // Since these are shared references, any changes in the values are reflected in
245 //! // the list.
246 //! a.value.set(7);
247 //! assert_eq!(list2.iter().map(|x| x.value.get()).collect::<Vec<_>>(), [7, 5, 6]);
248 //! ```
249 //!
250 //! # Safety
251 //!
252 //! While it is possible to use intrusive collections without any unsafe code,
253 //! this crate also exposes a few unsafe features.
254 //!
255 //! The `cursor_from_ptr` and `cursor_mut_from_ptr` allow you to create a
256 //! cursor pointing to a specific element in the collection from a pointer to
257 //! that element. This is unsafe because it assumes that the objected pointed to
258 //! is currently inserted in the collection.
259 //!
260 //! The `UnsafeRef` type acts like `Rc`, except without the reference count.
261 //! Instead, you are responsible for keeping track of the number of active
262 //! references to an object and for freeing it once the last reference is
263 //! dropped. The advantage of `UnsafeRef` over `Rc` is that it reduces the size
264 //! of the allocation by two `usize` and avoids the overhead of maintaining
265 //! reference counts.
266 
267 #![warn(missing_docs)]
268 #![warn(rust_2018_idioms)]
269 #![no_std]
270 #![cfg_attr(feature = "nightly", feature(const_fn))]
271 #![allow(clippy::declare_interior_mutable_const, clippy::collapsible_if)]
272 
273 #[cfg(feature = "alloc")]
274 extern crate alloc;
275 
276 #[cfg(test)]
277 extern crate std;
278 
279 mod unsafe_ref;
280 #[macro_use]
281 mod adapter;
282 mod key_adapter;
283 mod link_ops;
284 mod pointer_ops;
285 mod unchecked_option;
286 
287 pub mod linked_list;
288 pub mod rbtree;
289 pub mod singly_linked_list;
290 pub mod xor_linked_list;
291 
292 pub use crate::adapter::Adapter;
293 pub use crate::key_adapter::KeyAdapter;
294 pub use crate::link_ops::{DefaultLinkOps, LinkOps};
295 pub use crate::linked_list::Link as LinkedListLink;
296 pub use crate::linked_list::LinkedList;
297 pub use crate::pointer_ops::{DefaultPointerOps, PointerOps};
298 pub use crate::rbtree::Link as RBTreeLink;
299 pub use crate::rbtree::RBTree;
300 pub use crate::singly_linked_list::Link as SinglyLinkedListLink;
301 pub use crate::singly_linked_list::SinglyLinkedList;
302 pub use crate::unsafe_ref::UnsafeRef;
303 pub use crate::xor_linked_list::Link as XorLinkedListLink;
304 pub use crate::xor_linked_list::XorLinkedList;
305 pub use memoffset::offset_of;
306 
307 /// An endpoint of a range of keys.
308 #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
309 pub enum Bound<T> {
310     /// An inclusive bound.
311     Included(T),
312     /// An exclusive bound.
313     Excluded(T),
314     /// An infinite endpoint. Indicates that there is no bound in this direction.
315     Unbounded,
316 }
317