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