├── .github └── workflows │ └── ci.yml ├── .gitignore ├── Cargo.toml ├── DESIGN.md ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md └── src ├── adapter.rs ├── key_adapter.rs ├── lib.rs ├── link_ops.rs ├── linked_list.rs ├── pointer_ops.rs ├── rbtree.rs ├── singly_linked_list.rs ├── unchecked_option.rs ├── unsafe_ref.rs └── xor_linked_list.rs /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | 2 | name: CI 3 | on: [push, pull_request] 4 | jobs: 5 | test: 6 | name: Test 7 | runs-on: ubuntu-latest 8 | strategy: 9 | fail-fast: false 10 | matrix: 11 | rust: [1.56.1, stable, beta, nightly] 12 | steps: 13 | - name: Checkout 14 | uses: actions/checkout@v2 15 | - name: Install rust 16 | uses: actions-rs/toolchain@v1 17 | with: 18 | toolchain: ${{ matrix.rust }} 19 | profile: minimal 20 | override: true 21 | - uses: actions-rs/cargo@v1 22 | with: 23 | command: test 24 | - if: matrix.rust == 'nightly' 25 | uses: actions-rs/cargo@v1 26 | with: 27 | command: test 28 | args: --features nightly 29 | fmt: 30 | name: Rustfmt 31 | runs-on: ubuntu-latest 32 | steps: 33 | - uses: actions/checkout@v2 34 | - uses: actions-rs/toolchain@v1 35 | with: 36 | profile: minimal 37 | toolchain: stable 38 | override: true 39 | - run: rustup component add rustfmt 40 | - uses: actions-rs/cargo@v1 41 | with: 42 | command: fmt 43 | args: -- --check 44 | miri: 45 | name: Miri 46 | runs-on: ubuntu-latest 47 | steps: 48 | - uses: actions/checkout@v2 49 | - uses: actions-rs/toolchain@v1 50 | with: 51 | profile: minimal 52 | toolchain: nightly 53 | override: true 54 | - run: rustup component add miri 55 | - run: cargo miri test --verbose --all-features -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | Cargo.lock 3 | .DS_Store -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "intrusive-collections" 3 | version = "0.9.7" 4 | authors = ["Amanieu d'Antras "] 5 | description = "Intrusive collections for Rust (linked list and red-black tree)" 6 | documentation = "https://docs.rs/intrusive-collections" 7 | license = "Apache-2.0/MIT" 8 | repository = "https://github.com/Amanieu/intrusive-rs" 9 | readme = "README.md" 10 | keywords = ["intrusive", "no_std", "list", "rbtree"] 11 | categories = ["data-structures", "no-std"] 12 | edition = "2018" 13 | 14 | [features] 15 | nightly = [] 16 | alloc = [] 17 | default = ["alloc"] 18 | 19 | [dependencies] 20 | memoffset = "0.9" 21 | 22 | [dev-dependencies] 23 | rand = "0.8.4" 24 | typed-arena = "2.0.1" 25 | rand_xorshift = "0.3.0" 26 | -------------------------------------------------------------------------------- /DESIGN.md: -------------------------------------------------------------------------------- 1 | # Design rationale 2 | 3 | > I always hear that intrusive collections can't be done in Rust (either "can't be done safely" or "can't be done as performantly as C++"). Can you elaborate on this? 4 | 5 | I would say that it is a combination of both "can't be done safely" and "can't be done as performantly as C++". You should keep in mind that C++ libraries such as [Boost.Intrusive](http://www.boost.org/doc/libs/release/doc/html/intrusive.html) don't exactly have a safe API and instead place a bunch of [requirements on the user](http://www.boost.org/doc/libs/1_53_0/doc/html/intrusive/usage.html#intrusive.usage.usage_lifetime) regarding object lifetimes. 6 | 7 | There are several factor that a Rust implementation of intrusive collections must take into account: 8 | 9 | 1. Elements in a collection can't have a pointer back to the collection itself since these would become invalid if the collection is moved. C++ doesn't suffer from this limitation because it can adjust these pointers in the move constructor. 10 | 11 | (Not that I'm complaining about Rust's lack of move constructors. Having to deal with move constructors introduces *a lot* of complexity for collection code due to exception safety issues.) 12 | 13 | This basically means that we have to use NULL-terminated linked lists instead of circular linked lists. It's very slightly slower (depending on who you ask), but generally not a big deal. This same restriction also applies to normal collection types in Rust. 14 | 15 | 2. Rust doesn't have any equivalent to C++'s "pointer to member" type to tell a collection type which struct field to use for the intrusive `Link` (basically the prev/next pointers in a linked list). Instead, we use an unsafe `Adapter` trait which describes how to convert between a `*const T` and `*const Link`. 16 | 17 | The `intrusive_adapter!` macro provides a safe and easy way of creating and adapter type. It uses `offset_of!` and `container_of!` internally in a way that is guaranteed to be safe. This macro only supports the case where the link is a direct field of the object type; more complicated scenarios (such as nested fields) require a manual implementation of `Adapter`. 18 | 19 | 3. You can't safely give out `&mut` references to elements in a collection due to the aliasing rules (an object may be part of multiple intrusive collections at once) and because it allows the user to "break" the links in a collection with code like `mem::replace(&mut obj.link, Link::new())`. 20 | 21 | Since we can only give out `&` references to collection elements, any mutability must be done through `Cell` / `RefCell` / `UnsafeCell`. 22 | 23 | 4. Objects must not be moved or destroyed while they are still linked into an intrusive collection. While this basically sounds like having the collection take a shared borrow of an object when inserting it, lifetimes aren't ideal for this since they effectively restrict the lifetime of the collection to a single function. 24 | 25 | The basic approach that `intrusive-collections` takes is that a collection *takes ownership* of an object, usually in the form of an owned pointer (`Box`, `Rc`, etc), and then returns the owned pointer back to the user when the object is removed from the collection. The owned pointer type is a generic parameter of the collection (through the `Adapter` trait). 26 | 27 | The case of `Box` is the simplest, since the collection becomes the sole owner of the object. `Rc` is more interesting since the ownership is shared. This enables inserting an object into multiple intrusive collections (with multiple `Link`s in the object) without needing to worry about the object moving or dropping while still in use. 28 | 29 | `intrusive-collection` also supports using `&'a T` as the owned pointer type. This allows shared ownership (you can keep accessing variables that have been inserted in the collection) without the need for reference counting. Safety is ensure by restricting the lifetime of the collection such that it does not outlive any objects that have been inserted into it. As a bonus, this also works with [arenas](https://crates.io/crates/typed-arena) which give out `&'a T` references to allocated objects. 30 | 31 | Finally, if you really need to avoid the overhead of `Rc`, the crate also provides an `UnsafeRef` type which acts like an `Rc` but without the reference count: you are expected to free the object yourself once you are sure it is no longer in use. 32 | 33 | So basically, `intrusive-collections` is almost as performant as C++ intrusive collections. If you want every last bit of performance, you can use `UnsafeRef` instead of `Rc` for the owned pointer and `UnsafeCell` instead of `RefCell` for the object data. However I would expect the gains to be relatively minor compared to the added unsafety. 34 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 Amanieu d'Antras 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | intrusive-collections 2 | ===================== 3 | 4 | [![Build Status](https://travis-ci.org/Amanieu/intrusive-rs.svg?branch=master)](https://travis-ci.org/Amanieu/intrusive-rs) [![Coverage Status](https://coveralls.io/repos/github/Amanieu/intrusive-rs/badge.svg?branch=master)](https://coveralls.io/github/Amanieu/intrusive-rs?branch=master) [![Crates.io](https://img.shields.io/crates/v/intrusive-collections.svg)](https://crates.io/crates/intrusive-collections) 5 | 6 | A Rust library for creating intrusive collections. Currently supports singly-linked and doubly-linked lists, as well as red-black trees. 7 | 8 | ## Features 9 | 10 | - Compatible with `#[no_std]`. 11 | - Intrusive collections don't require any dynamic memory allocation since they simply keep track of existing objects rather than allocating new ones. 12 | - You can safely manipulate intrusive collections without any unsafe code. 13 | - A single object can be a member of multiple intrusive collections simultaneously. 14 | - Intrusive collections provide a `Cursor`-based interface, which allows safe mutation while iterating. 15 | 16 | For examples and more information, see the documentation ([crates.io](https://docs.rs/intrusive-collections), [master](https://amanieu.github.io/intrusive-rs/intrusive_collections/index.html)). 17 | 18 | ## Usage 19 | 20 | Add this to your `Cargo.toml`: 21 | 22 | ```toml 23 | [dependencies] 24 | intrusive-collections = "0.9" 25 | ``` 26 | 27 | This crate has two Cargo features: 28 | 29 | - `nightly`: Enables nightly-only features: `const fn` constructors for collections (`Link` constructors are always `const fn`) 30 | - `alloc` (enabled by default): Implements `IntrusivePointer` for `Box`, `Rc` and `Arc`. 31 | 32 | ## License 33 | 34 | Licensed under either of 35 | 36 | * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) 37 | * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) 38 | 39 | at your option. 40 | 41 | ### Contribution 42 | 43 | Unless you explicitly state otherwise, any contribution intentionally submitted 44 | for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any 45 | additional terms or conditions. 46 | -------------------------------------------------------------------------------- /src/adapter.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Amanieu d'Antras 2 | // Copyright 2020 Amari Robinson 3 | // 4 | // Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be 7 | // copied, modified, or distributed except according to those terms. 8 | 9 | use crate::link_ops::LinkOps; 10 | use crate::pointer_ops::PointerOps; 11 | 12 | /// Trait for a adapter which allows a type to be inserted into an intrusive 13 | /// collection. 14 | /// 15 | /// `LinkOps` implements the collection-specific operations which 16 | /// allows an object to be inserted into an intrusive collection. This type 17 | /// needs to implement the appropriate trait for the collection type 18 | /// (eg. `LinkedListOps` for inserting into a `LinkedList`). 19 | /// `LinkOps` type may be stateful, allowing custom link types. 20 | /// 21 | /// `PointerOps` implements the collection-specific pointer conversions which 22 | /// allow an object to be inserted into an intrusive collection. 23 | /// `PointerOps` type may be stateful, allowing custom pointer types. 24 | /// 25 | /// A single object type may have multiple adapters, which allows it to be part 26 | /// of multiple intrusive collections simultaneously. 27 | /// 28 | /// In most cases you do not need to implement this trait manually: the 29 | /// `intrusive_adapter!` macro will generate the necessary implementation for a 30 | /// given type and its link field. However it is possible to implement it 31 | /// manually if the intrusive link is not a direct field of the object type. 32 | /// 33 | /// It is also possible to create stateful adapters. 34 | /// This allows links and containers to be separated and avoids the need for objects to be modified to 35 | /// contain a link. 36 | /// 37 | /// # Safety 38 | /// 39 | /// It must be possible to get back a reference to the container by passing a 40 | /// pointer returned by `get_link` to `get_container`. 41 | pub unsafe trait Adapter { 42 | /// Collection-specific link operations which allow an object to be inserted in 43 | /// an intrusive collection. 44 | type LinkOps: LinkOps; 45 | 46 | /// Collection-specific pointer conversions which allow an object to 47 | /// be inserted in an intrusive collection. 48 | type PointerOps: PointerOps; 49 | 50 | /// Gets a reference to an object from a reference to a link in that object. 51 | /// 52 | /// # Safety 53 | /// 54 | /// `link` must be a valid pointer previously returned by `get_link`. 55 | unsafe fn get_value( 56 | &self, 57 | link: ::LinkPtr, 58 | ) -> *const ::Value; 59 | 60 | /// Gets a reference to the link for the given object. 61 | /// 62 | /// # Safety 63 | /// 64 | /// `value` must be a valid pointer. 65 | unsafe fn get_link( 66 | &self, 67 | value: *const ::Value, 68 | ) -> ::LinkPtr; 69 | 70 | /// Returns a reference to the link operations. 71 | fn link_ops(&self) -> &Self::LinkOps; 72 | 73 | /// Returns a reference to the mutable link operations. 74 | fn link_ops_mut(&mut self) -> &mut Self::LinkOps; 75 | 76 | /// Returns a reference to the pointer converter. 77 | fn pointer_ops(&self) -> &Self::PointerOps; 78 | } 79 | 80 | /// Unsafe macro to get a raw pointer to an outer object from a pointer to one 81 | /// of its fields. 82 | /// 83 | /// # Examples 84 | /// 85 | /// ``` 86 | /// use intrusive_collections::container_of; 87 | /// 88 | /// struct S { x: u32, y: u32 }; 89 | /// let container = S { x: 1, y: 2 }; 90 | /// let field = &container.x; 91 | /// let container2: *const S = unsafe { container_of!(field, S, x) }; 92 | /// assert_eq!(&container as *const S, container2); 93 | /// ``` 94 | /// 95 | /// # Safety 96 | /// 97 | /// This is unsafe because it assumes that the given expression is a valid 98 | /// pointer to the specified field of some container type. 99 | #[macro_export] 100 | macro_rules! container_of { 101 | ($ptr:expr, $container:path, $field:ident) => { 102 | #[allow(clippy::cast_ptr_alignment)] 103 | { 104 | ($ptr as *const _ as *const u8).sub($crate::offset_of!($container, $field)) 105 | as *const $container 106 | } 107 | }; 108 | } 109 | 110 | /// Macro to generate an implementation of `Adapter` for a given set of types. 111 | /// In particular this will automatically generate implementations of the 112 | /// `get_value` and `get_link` methods for a given named field in a struct. 113 | /// 114 | /// The basic syntax to create an adapter is: 115 | /// 116 | /// ```rust,ignore 117 | /// intrusive_adapter!(Adapter = Pointer: Value { link_field: LinkType }); 118 | /// ``` 119 | /// 120 | /// You can create a new instance of an adapter using the `new` method or the 121 | /// `NEW` associated constant. The adapter also implements the `Default` trait. 122 | /// 123 | /// # Generics 124 | /// 125 | /// This macro supports generic arguments: 126 | /// 127 | /// ```rust,ignore 128 | /// intrusive_adapter!( 129 | /// Adapter<'lifetime, Type, Type2> = 130 | /// Pointer: Value { 131 | /// link_field: LinkType 132 | /// } 133 | /// where 134 | /// Type: Copy, 135 | /// Type2: ?Sized + 'lifetime 136 | /// ); 137 | /// ``` 138 | /// 139 | /// Note that due to macro parsing limitations, `T: Trait` bounds are not 140 | /// supported in the generic argument list. You must list any trait bounds in 141 | /// a separate `where` clause at the end of the macro. 142 | /// 143 | /// # Examples 144 | /// 145 | /// ``` 146 | /// use intrusive_collections::{LinkedListLink, RBTreeLink}; 147 | /// use intrusive_collections::intrusive_adapter; 148 | /// 149 | /// pub struct Test { 150 | /// link: LinkedListLink, 151 | /// link2: RBTreeLink, 152 | /// } 153 | /// intrusive_adapter!(MyAdapter = Box: Test { link: LinkedListLink }); 154 | /// intrusive_adapter!(pub MyAdapter2 = Box: Test { link2: RBTreeLink }); 155 | /// intrusive_adapter!(pub(crate) MyAdapter3 = Box: Test { link2: RBTreeLink }); 156 | /// 157 | /// pub struct Test2 158 | /// where T: Clone + ?Sized 159 | /// { 160 | /// link: LinkedListLink, 161 | /// val: T, 162 | /// } 163 | /// intrusive_adapter!(MyAdapter4<'a, T> = &'a Test2: Test2 { link: LinkedListLink } where T: ?Sized + Clone + 'a); 164 | /// ``` 165 | #[macro_export] 166 | macro_rules! intrusive_adapter { 167 | (@impl 168 | $(#[$attr:meta])* $vis:vis $name:ident ($($args:tt),*) 169 | = $pointer:ty: $value:path { $field:ident: $link:ty } $($where_:tt)* 170 | ) => { 171 | #[allow(explicit_outlives_requirements)] 172 | $(#[$attr])* 173 | $vis struct $name<$($args),*> $($where_)* { 174 | link_ops: <$link as $crate::DefaultLinkOps>::Ops, 175 | pointer_ops: $crate::DefaultPointerOps<$pointer>, 176 | } 177 | unsafe impl<$($args),*> Send for $name<$($args),*> $($where_)* {} 178 | unsafe impl<$($args),*> Sync for $name<$($args),*> $($where_)* {} 179 | impl<$($args),*> Copy for $name<$($args),*> $($where_)* {} 180 | impl<$($args),*> Clone for $name<$($args),*> $($where_)* { 181 | #[inline] 182 | fn clone(&self) -> Self { 183 | *self 184 | } 185 | } 186 | impl<$($args),*> Default for $name<$($args),*> $($where_)* { 187 | #[inline] 188 | fn default() -> Self { 189 | Self::NEW 190 | } 191 | } 192 | #[allow(dead_code)] 193 | impl<$($args),*> $name<$($args),*> $($where_)* { 194 | pub const NEW: Self = $name { 195 | link_ops: <$link as $crate::DefaultLinkOps>::NEW, 196 | pointer_ops: $crate::DefaultPointerOps::<$pointer>::new(), 197 | }; 198 | #[inline] 199 | pub fn new() -> Self { 200 | Self::NEW 201 | } 202 | } 203 | #[allow(dead_code, unsafe_code)] 204 | unsafe impl<$($args),*> $crate::Adapter for $name<$($args),*> $($where_)* { 205 | type LinkOps = <$link as $crate::DefaultLinkOps>::Ops; 206 | type PointerOps = $crate::DefaultPointerOps<$pointer>; 207 | 208 | #[inline] 209 | unsafe fn get_value(&self, link: ::LinkPtr) -> *const ::Value { 210 | $crate::container_of!(link.as_ptr(), $value, $field) 211 | } 212 | #[inline] 213 | unsafe fn get_link(&self, value: *const ::Value) -> ::LinkPtr { 214 | // We need to do this instead of just accessing the field directly 215 | // to strictly follow the stack borrow rules. 216 | let ptr = (value as *const u8).add($crate::offset_of!($value, $field)); 217 | core::ptr::NonNull::new_unchecked(ptr as *mut _) 218 | } 219 | #[inline] 220 | fn link_ops(&self) -> &Self::LinkOps { 221 | &self.link_ops 222 | } 223 | #[inline] 224 | fn link_ops_mut(&mut self) -> &mut Self::LinkOps { 225 | &mut self.link_ops 226 | } 227 | #[inline] 228 | fn pointer_ops(&self) -> &Self::PointerOps { 229 | &self.pointer_ops 230 | } 231 | } 232 | }; 233 | (@find_generic 234 | $(#[$attr:meta])* $vis:vis $name:ident ($($prev:tt)*) > $($rest:tt)* 235 | ) => { 236 | intrusive_adapter!(@impl 237 | $(#[$attr])* $vis $name ($($prev)*) $($rest)* 238 | ); 239 | }; 240 | (@find_generic 241 | $(#[$attr:meta])* $vis:vis $name:ident ($($prev:tt)*) $cur:tt $($rest:tt)* 242 | ) => { 243 | intrusive_adapter!(@find_generic 244 | $(#[$attr])* $vis $name ($($prev)* $cur) $($rest)* 245 | ); 246 | }; 247 | (@find_if_generic 248 | $(#[$attr:meta])* $vis:vis $name:ident < $($rest:tt)* 249 | ) => { 250 | intrusive_adapter!(@find_generic 251 | $(#[$attr])* $vis $name () $($rest)* 252 | ); 253 | }; 254 | (@find_if_generic 255 | $(#[$attr:meta])* $vis:vis $name:ident $($rest:tt)* 256 | ) => { 257 | intrusive_adapter!(@impl 258 | $(#[$attr])* $vis $name () $($rest)* 259 | ); 260 | }; 261 | ($(#[$attr:meta])* $vis:vis $name:ident $($rest:tt)*) => { 262 | intrusive_adapter!(@find_if_generic 263 | $(#[$attr])* $vis $name $($rest)* 264 | ); 265 | }; 266 | } 267 | 268 | #[cfg(test)] 269 | mod tests { 270 | use crate::LinkedListLink; 271 | use std::rc::Rc; 272 | 273 | struct Obj { 274 | link: LinkedListLink, 275 | } 276 | 277 | intrusive_adapter! { 278 | /// Test doc comment 279 | ObjAdapter1 = Rc: Obj { link: LinkedListLink } 280 | } 281 | } 282 | -------------------------------------------------------------------------------- /src/key_adapter.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Amanieu d'Antras 2 | // Copyright 2020 Amari Robinson 3 | // 4 | // Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be 7 | // copied, modified, or distributed except according to those terms. 8 | 9 | use crate::adapter::Adapter; 10 | use crate::pointer_ops::PointerOps; 11 | 12 | /// Extension of the `Adapter` trait to provide a way of extracting a key from 13 | /// an object. This key can then be used as an index in certain intrusive 14 | /// collections (currently only `RBTree` uses this). 15 | /// 16 | /// The key can be returned either as a value or as a reference, which allows 17 | /// you to 18 | /// 19 | /// # Examples 20 | /// 21 | /// ``` 22 | /// use intrusive_collections::intrusive_adapter; 23 | /// use intrusive_collections::{RBTreeLink, KeyAdapter}; 24 | /// 25 | /// struct S { 26 | /// link: RBTreeLink, 27 | /// key: u32, 28 | /// value: u64, 29 | /// } 30 | /// 31 | /// // Adapter which returns a key by value 32 | /// intrusive_adapter!(MyAdapter = Box: S { link : RBTreeLink }); 33 | /// impl<'a> KeyAdapter<'a> for MyAdapter { 34 | /// type Key = u32; 35 | /// fn get_key(&self, s: &'a S) -> u32 { s.key } 36 | /// } 37 | /// 38 | /// // Adapter which returns a key by reference 39 | /// intrusive_adapter!(MyAdapter2 = Box: S { link : RBTreeLink }); 40 | /// impl<'a> KeyAdapter<'a> for MyAdapter2 { 41 | /// type Key = &'a u32; 42 | /// fn get_key(&self, s: &'a S) -> &'a u32 { &s.key } 43 | /// } 44 | /// 45 | /// struct U { 46 | /// link: RBTreeLink, 47 | /// key1: i32, 48 | /// key2: String, 49 | /// key3: f64, 50 | /// } 51 | /// 52 | /// // Adapter which returns a tuple as a key. When used in a RBTree, this will 53 | /// // keep all elements sorted by `key1` first, then `key2` and finally `key3`. 54 | /// intrusive_adapter!(MyAdapter3 = Box: U { link : RBTreeLink }); 55 | /// impl<'a> KeyAdapter<'a> for MyAdapter3 { 56 | /// type Key = (i32, &'a str, f64); 57 | /// fn get_key(&self, u: &'a U) -> Self::Key { (u.key1, &u.key2, u.key3) } 58 | /// } 59 | /// ``` 60 | pub trait KeyAdapter<'a>: Adapter { 61 | /// Type of the key returned by `get_key`. 62 | type Key; 63 | 64 | /// Gets the key for the given object. 65 | fn get_key(&self, value: &'a ::Value) -> Self::Key; 66 | } 67 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Amanieu d'Antras 2 | // Copyright 2020 Amari Robinson 3 | // 4 | // Licensed under the Apache License, Version 2.0, or the MIT license , 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, 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 { 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::>(), [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::>(), [4, 2, 1]); 63 | //! 64 | //! // Removing an object from an instrusive collection gives us back the 65 | //! // Box 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::>(), [2, 1]); 69 | //! 70 | //! // Dropping the collection will automatically free b and c by 71 | //! // transforming them back into Box 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 { link: LinkedListLink }); 110 | //! intrusive_adapter!(MyAdapter2 = Rc: Test { link2: SinglyLinkedListLink }); 111 | //! intrusive_adapter!(MyAdapter3 = Rc: Test { link3: XorLinkedListLink }); 112 | //! intrusive_adapter!(MyAdapter4 = Rc: 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 { 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, 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(), 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, 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::>(), [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::>(), [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::>(), [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_trait_bound))] 271 | #![allow( 272 | clippy::declare_interior_mutable_const, 273 | clippy::collapsible_if, 274 | clippy::collapsible_else_if 275 | )] 276 | 277 | #[cfg(feature = "alloc")] 278 | extern crate alloc; 279 | 280 | #[cfg(test)] 281 | extern crate std; 282 | 283 | mod unsafe_ref; 284 | #[macro_use] 285 | mod adapter; 286 | mod key_adapter; 287 | mod link_ops; 288 | mod pointer_ops; 289 | mod unchecked_option; 290 | 291 | pub mod linked_list; 292 | pub mod rbtree; 293 | pub mod singly_linked_list; 294 | pub mod xor_linked_list; 295 | 296 | pub use crate::adapter::Adapter; 297 | pub use crate::key_adapter::KeyAdapter; 298 | pub use crate::link_ops::{DefaultLinkOps, LinkOps}; 299 | pub use crate::linked_list::AtomicLink as LinkedListAtomicLink; 300 | pub use crate::linked_list::Link as LinkedListLink; 301 | pub use crate::linked_list::LinkedList; 302 | pub use crate::pointer_ops::{DefaultPointerOps, PointerOps}; 303 | pub use crate::rbtree::AtomicLink as RBTreeAtomicLink; 304 | pub use crate::rbtree::Link as RBTreeLink; 305 | pub use crate::rbtree::RBTree; 306 | pub use crate::singly_linked_list::AtomicLink as SinglyLinkedListAtomicLink; 307 | pub use crate::singly_linked_list::Link as SinglyLinkedListLink; 308 | pub use crate::singly_linked_list::SinglyLinkedList; 309 | pub use crate::unsafe_ref::UnsafeRef; 310 | pub use crate::xor_linked_list::AtomicLink as XorLinkedListAtomicLink; 311 | pub use crate::xor_linked_list::Link as XorLinkedListLink; 312 | pub use crate::xor_linked_list::XorLinkedList; 313 | pub use memoffset::offset_of; 314 | 315 | /// An endpoint of a range of keys. 316 | #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] 317 | pub enum Bound { 318 | /// An inclusive bound. 319 | Included(T), 320 | /// An exclusive bound. 321 | Excluded(T), 322 | /// An infinite endpoint. Indicates that there is no bound in this direction. 323 | Unbounded, 324 | } 325 | -------------------------------------------------------------------------------- /src/link_ops.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Amari Robinson 2 | // 3 | // Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be 6 | // copied, modified, or distributed except according to those terms. 7 | 8 | /// Base trait for link operations. 9 | /// 10 | /// `LinkPtr` is the representation of a link pointer. 11 | /// Typically this is `NonNull`, but compact representations such 12 | /// as `u8` or `u16` are possible. 13 | pub unsafe trait LinkOps { 14 | /// The link pointer type. 15 | type LinkPtr: Copy + Eq; 16 | 17 | /// Attempts to acquire ownership of a link so that it can be used in an 18 | /// intrusive collection. 19 | /// 20 | /// If this function succeeds then the intrusive collection will have 21 | /// exclusive access to the link until `release_link` is called. 22 | unsafe fn acquire_link(&mut self, ptr: Self::LinkPtr) -> bool; 23 | 24 | /// Releases ownership of a link that was previously acquired with `acquire_link`. 25 | /// 26 | /// # Safety 27 | /// An implementation of `release_link` must not panic. 28 | unsafe fn release_link(&mut self, ptr: Self::LinkPtr); 29 | } 30 | 31 | /// The default implementation of `LinkOps` associated with a link type. 32 | pub trait DefaultLinkOps { 33 | /// The default link operations. 34 | type Ops: LinkOps + Default; 35 | 36 | /// The associated constant that represents `Ops::default()`. 37 | /// 38 | /// This exists because `Default::default()` is not a constant function. 39 | const NEW: Self::Ops; 40 | } 41 | -------------------------------------------------------------------------------- /src/linked_list.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Amanieu d'Antras 2 | // Copyright 2020 Amari Robinson 3 | // 4 | // Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be 7 | // copied, modified, or distributed except according to those terms. 8 | 9 | //! Intrusive doubly-linked list. 10 | 11 | use core::cell::Cell; 12 | use core::fmt; 13 | use core::ptr::{null_mut, NonNull}; 14 | use core::sync::atomic::{AtomicPtr, Ordering}; 15 | 16 | use crate::link_ops::{self, DefaultLinkOps}; 17 | use crate::pointer_ops::PointerOps; 18 | use crate::singly_linked_list::SinglyLinkedListOps; 19 | use crate::xor_linked_list::XorLinkedListOps; 20 | use crate::Adapter; 21 | // Necessary for Rust 1.56 compatability 22 | #[allow(unused_imports)] 23 | use crate::unchecked_option::UncheckedOptionExt; 24 | 25 | // ============================================================================= 26 | // LinkedListOps 27 | // ============================================================================= 28 | 29 | /// Link operations for `LinkedList`. 30 | pub unsafe trait LinkedListOps: link_ops::LinkOps { 31 | /// Returns the "next" link pointer of `ptr`. 32 | /// 33 | /// # Safety 34 | /// An implementation of `next` must not panic. 35 | unsafe fn next(&self, ptr: Self::LinkPtr) -> Option; 36 | 37 | /// Returns the "prev" link pointer of `ptr`. 38 | /// 39 | /// # Safety 40 | /// An implementation of `prev` must not panic. 41 | unsafe fn prev(&self, ptr: Self::LinkPtr) -> Option; 42 | 43 | /// Sets the "next" link pointer of `ptr`. 44 | /// 45 | /// # Safety 46 | /// An implementation of `set_next` must not panic. 47 | unsafe fn set_next(&mut self, ptr: Self::LinkPtr, next: Option); 48 | 49 | /// Sets the "prev" link pointer of `ptr`. 50 | /// 51 | /// # Safety 52 | /// An implementation of `set_prev` must not panic. 53 | unsafe fn set_prev(&mut self, ptr: Self::LinkPtr, prev: Option); 54 | } 55 | 56 | // ============================================================================= 57 | // Link 58 | // ============================================================================= 59 | 60 | /// Intrusive link that allows an object to be inserted into a 61 | /// `LinkedList`. 62 | #[repr(align(2))] 63 | pub struct Link { 64 | next: Cell>>, 65 | prev: Cell>>, 66 | } 67 | 68 | // Use a special value to indicate an unlinked node 69 | const UNLINKED_MARKER: Option> = 70 | unsafe { Some(NonNull::new_unchecked(1 as *mut Link)) }; 71 | 72 | impl Link { 73 | /// Creates a new `Link`. 74 | #[inline] 75 | pub const fn new() -> Link { 76 | Link { 77 | next: Cell::new(UNLINKED_MARKER), 78 | prev: Cell::new(UNLINKED_MARKER), 79 | } 80 | } 81 | 82 | /// Checks whether the `Link` is linked into a `LinkedList`. 83 | #[inline] 84 | pub fn is_linked(&self) -> bool { 85 | self.next.get() != UNLINKED_MARKER 86 | } 87 | 88 | /// Forcibly unlinks an object from a `LinkedList`. 89 | /// 90 | /// # Safety 91 | /// 92 | /// It is undefined behavior to call this function while still linked into a 93 | /// `LinkedList`. The only situation where this function is useful is 94 | /// after calling `fast_clear` on a `LinkedList`, since this clears 95 | /// the collection without marking the nodes as unlinked. 96 | #[inline] 97 | pub unsafe fn force_unlink(&self) { 98 | self.next.set(UNLINKED_MARKER); 99 | } 100 | } 101 | 102 | impl DefaultLinkOps for Link { 103 | type Ops = LinkOps; 104 | 105 | const NEW: Self::Ops = LinkOps; 106 | } 107 | 108 | // An object containing a link can be sent to another thread if it is unlinked. 109 | unsafe impl Send for Link {} 110 | 111 | // Provide an implementation of Clone which simply initializes the new link as 112 | // unlinked. This allows structs containing a link to derive Clone. 113 | impl Clone for Link { 114 | #[inline] 115 | fn clone(&self) -> Link { 116 | Link::new() 117 | } 118 | } 119 | 120 | // Same as above 121 | impl Default for Link { 122 | #[inline] 123 | fn default() -> Link { 124 | Link::new() 125 | } 126 | } 127 | 128 | // Provide an implementation of Debug so that structs containing a link can 129 | // still derive Debug. 130 | impl fmt::Debug for Link { 131 | #[inline] 132 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 133 | // There isn't anything sensible to print here except whether the link 134 | // is currently in a list. 135 | if self.is_linked() { 136 | write!(f, "linked") 137 | } else { 138 | write!(f, "unlinked") 139 | } 140 | } 141 | } 142 | 143 | // ============================================================================= 144 | // LinkOps 145 | // ============================================================================= 146 | 147 | /// Default `LinkOps` implementation for `LinkedList`. 148 | #[derive(Clone, Copy, Default)] 149 | pub struct LinkOps; 150 | 151 | unsafe impl link_ops::LinkOps for LinkOps { 152 | type LinkPtr = NonNull; 153 | 154 | #[inline] 155 | unsafe fn acquire_link(&mut self, ptr: Self::LinkPtr) -> bool { 156 | if ptr.as_ref().is_linked() { 157 | false 158 | } else { 159 | ptr.as_ref().next.set(None); 160 | true 161 | } 162 | } 163 | 164 | #[inline] 165 | unsafe fn release_link(&mut self, ptr: Self::LinkPtr) { 166 | ptr.as_ref().next.set(UNLINKED_MARKER); 167 | } 168 | } 169 | 170 | unsafe impl LinkedListOps for LinkOps { 171 | #[inline] 172 | unsafe fn next(&self, ptr: Self::LinkPtr) -> Option { 173 | ptr.as_ref().next.get() 174 | } 175 | 176 | #[inline] 177 | unsafe fn prev(&self, ptr: Self::LinkPtr) -> Option { 178 | ptr.as_ref().prev.get() 179 | } 180 | 181 | #[inline] 182 | unsafe fn set_next(&mut self, ptr: Self::LinkPtr, next: Option) { 183 | ptr.as_ref().next.set(next); 184 | } 185 | 186 | #[inline] 187 | unsafe fn set_prev(&mut self, ptr: Self::LinkPtr, prev: Option) { 188 | ptr.as_ref().prev.set(prev); 189 | } 190 | } 191 | 192 | unsafe impl SinglyLinkedListOps for LinkOps { 193 | #[inline] 194 | unsafe fn next(&self, ptr: Self::LinkPtr) -> Option { 195 | ptr.as_ref().next.get() 196 | } 197 | 198 | #[inline] 199 | unsafe fn set_next(&mut self, ptr: Self::LinkPtr, next: Option) { 200 | ptr.as_ref().next.set(next); 201 | } 202 | } 203 | 204 | unsafe impl XorLinkedListOps for LinkOps { 205 | #[inline] 206 | unsafe fn next( 207 | &self, 208 | ptr: Self::LinkPtr, 209 | prev: Option, 210 | ) -> Option { 211 | let packed = ptr 212 | .as_ref() 213 | .next 214 | .get() 215 | .map(|x| x.as_ptr() as usize) 216 | .unwrap_or(0); 217 | let raw = packed ^ prev.map(|x| x.as_ptr() as usize).unwrap_or(0); 218 | NonNull::new(raw as *mut _) 219 | } 220 | 221 | #[inline] 222 | unsafe fn prev( 223 | &self, 224 | ptr: Self::LinkPtr, 225 | next: Option, 226 | ) -> Option { 227 | let packed = ptr 228 | .as_ref() 229 | .next 230 | .get() 231 | .map(|x| x.as_ptr() as usize) 232 | .unwrap_or(0); 233 | let raw = packed ^ next.map(|x| x.as_ptr() as usize).unwrap_or(0); 234 | NonNull::new(raw as *mut _) 235 | } 236 | 237 | #[inline] 238 | unsafe fn set( 239 | &mut self, 240 | ptr: Self::LinkPtr, 241 | prev: Option, 242 | next: Option, 243 | ) { 244 | let new_packed = prev.map(|x| x.as_ptr() as usize).unwrap_or(0) 245 | ^ next.map(|x| x.as_ptr() as usize).unwrap_or(0); 246 | 247 | let new_next = NonNull::new(new_packed as *mut _); 248 | ptr.as_ref().next.set(new_next); 249 | } 250 | 251 | #[inline] 252 | unsafe fn replace_next_or_prev( 253 | &mut self, 254 | ptr: Self::LinkPtr, 255 | old: Option, 256 | new: Option, 257 | ) { 258 | let packed = ptr 259 | .as_ref() 260 | .next 261 | .get() 262 | .map(|x| x.as_ptr() as usize) 263 | .unwrap_or(0); 264 | let new_packed = packed 265 | ^ old.map(|x| x.as_ptr() as usize).unwrap_or(0) 266 | ^ new.map(|x| x.as_ptr() as usize).unwrap_or(0); 267 | 268 | let new_next = NonNull::new(new_packed as *mut _); 269 | ptr.as_ref().next.set(new_next); 270 | } 271 | } 272 | 273 | // ============================================================================= 274 | // AtomicLink 275 | // ============================================================================= 276 | 277 | /// Intrusive atomic link that allows an object to be inserted into a 278 | /// `LinkedList`. This link allows the structure to be shared between threads. 279 | #[repr(align(2))] 280 | pub struct AtomicLink { 281 | next: AtomicPtr, 282 | prev: Cell>>, 283 | } 284 | 285 | // Use a special value to indicate an unlinked node 286 | const ATOMIC_UNLINKED_MARKER_PTR: *mut AtomicLink = 1 as *mut AtomicLink; 287 | 288 | // Use a special value to indicate an unlinked node 289 | const ATOMIC_UNLINKED_MARKER: Option> = 290 | unsafe { Some(NonNull::new_unchecked(ATOMIC_UNLINKED_MARKER_PTR)) }; 291 | 292 | impl AtomicLink { 293 | /// Creates a new `AtomicLink`. 294 | #[inline] 295 | pub const fn new() -> AtomicLink { 296 | Self { 297 | next: AtomicPtr::new(ATOMIC_UNLINKED_MARKER_PTR), 298 | prev: Cell::new(ATOMIC_UNLINKED_MARKER), 299 | } 300 | } 301 | 302 | /// Checks whether the `AtomicLink` is linked into a `LinkedList`. 303 | #[inline] 304 | pub fn is_linked(&self) -> bool { 305 | self.next.load(Ordering::Relaxed) != ATOMIC_UNLINKED_MARKER_PTR 306 | } 307 | 308 | /// Forcibly unlinks an object from a `LinkedList`. 309 | /// 310 | /// # Safety 311 | /// 312 | /// It is undefined behavior to call this function while still linked into a 313 | /// `LinkedList`. The only situation where this function is useful is 314 | /// after calling `fast_clear` on a `LinkedList`, since this clears 315 | /// the collection without marking the nodes as unlinked. 316 | #[inline] 317 | pub unsafe fn force_unlink(&self) { 318 | self.next 319 | .store(ATOMIC_UNLINKED_MARKER_PTR, Ordering::Release) 320 | } 321 | 322 | /// Access the `next` pointer in an exclusive context. 323 | /// 324 | /// # Safety 325 | /// 326 | /// This can only be called after `acquire_link` has been succesfully called. 327 | #[inline] 328 | unsafe fn next_exclusive(&self) -> &Cell>> { 329 | // This is safe because currently AtomicPtr has the same representation Cell>>. 330 | core::mem::transmute(&self.next) 331 | } 332 | } 333 | 334 | impl DefaultLinkOps for AtomicLink { 335 | type Ops = AtomicLinkOps; 336 | 337 | const NEW: Self::Ops = AtomicLinkOps; 338 | } 339 | 340 | // An object containing a link can be sent to another thread since `acquire_link` is atomic. 341 | unsafe impl Send for AtomicLink {} 342 | 343 | // An object containing a link can be shared between threads since `acquire_link` is atomic. 344 | unsafe impl Sync for AtomicLink {} 345 | 346 | impl Clone for AtomicLink { 347 | #[inline] 348 | fn clone(&self) -> AtomicLink { 349 | AtomicLink::new() 350 | } 351 | } 352 | 353 | impl Default for AtomicLink { 354 | #[inline] 355 | fn default() -> AtomicLink { 356 | AtomicLink::new() 357 | } 358 | } 359 | 360 | // Provide an implementation of Debug so that structs containing a link can 361 | // still derive Debug. 362 | impl fmt::Debug for AtomicLink { 363 | #[inline] 364 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 365 | // There isn't anything sensible to print here except whether the link 366 | // is currently in a list. 367 | if self.is_linked() { 368 | write!(f, "linked") 369 | } else { 370 | write!(f, "unlinked") 371 | } 372 | } 373 | } 374 | 375 | // ============================================================================= 376 | // AtomicLinkOps 377 | // ============================================================================= 378 | 379 | /// Default `AtomicLinkOps` implementation for `LinkedList`. 380 | #[derive(Clone, Copy, Default)] 381 | pub struct AtomicLinkOps; 382 | 383 | unsafe impl link_ops::LinkOps for AtomicLinkOps { 384 | type LinkPtr = NonNull; 385 | 386 | #[inline] 387 | unsafe fn acquire_link(&mut self, ptr: Self::LinkPtr) -> bool { 388 | ptr.as_ref() 389 | .next 390 | .compare_exchange( 391 | ATOMIC_UNLINKED_MARKER_PTR, 392 | null_mut(), 393 | Ordering::Acquire, 394 | Ordering::Relaxed, 395 | ) 396 | .is_ok() 397 | } 398 | 399 | #[inline] 400 | unsafe fn release_link(&mut self, ptr: Self::LinkPtr) { 401 | ptr.as_ref() 402 | .next 403 | .store(ATOMIC_UNLINKED_MARKER_PTR, Ordering::Release) 404 | } 405 | } 406 | 407 | unsafe impl LinkedListOps for AtomicLinkOps { 408 | #[inline] 409 | unsafe fn next(&self, ptr: Self::LinkPtr) -> Option { 410 | ptr.as_ref().next_exclusive().get() 411 | } 412 | 413 | #[inline] 414 | unsafe fn prev(&self, ptr: Self::LinkPtr) -> Option { 415 | ptr.as_ref().prev.get() 416 | } 417 | 418 | #[inline] 419 | unsafe fn set_next(&mut self, ptr: Self::LinkPtr, next: Option) { 420 | ptr.as_ref().next_exclusive().set(next); 421 | } 422 | 423 | #[inline] 424 | unsafe fn set_prev(&mut self, ptr: Self::LinkPtr, prev: Option) { 425 | ptr.as_ref().prev.set(prev); 426 | } 427 | } 428 | 429 | unsafe impl SinglyLinkedListOps for AtomicLinkOps { 430 | #[inline] 431 | unsafe fn next(&self, ptr: Self::LinkPtr) -> Option { 432 | ptr.as_ref().next_exclusive().get() 433 | } 434 | 435 | #[inline] 436 | unsafe fn set_next(&mut self, ptr: Self::LinkPtr, next: Option) { 437 | ptr.as_ref().next_exclusive().set(next); 438 | } 439 | } 440 | 441 | unsafe impl XorLinkedListOps for AtomicLinkOps { 442 | #[inline] 443 | unsafe fn next( 444 | &self, 445 | ptr: Self::LinkPtr, 446 | prev: Option, 447 | ) -> Option { 448 | let packed = ptr 449 | .as_ref() 450 | .next_exclusive() 451 | .get() 452 | .map(|x| x.as_ptr() as usize) 453 | .unwrap_or(0); 454 | let raw = packed ^ prev.map(|x| x.as_ptr() as usize).unwrap_or(0); 455 | NonNull::new(raw as *mut _) 456 | } 457 | 458 | #[inline] 459 | unsafe fn prev( 460 | &self, 461 | ptr: Self::LinkPtr, 462 | next: Option, 463 | ) -> Option { 464 | let packed = ptr 465 | .as_ref() 466 | .next_exclusive() 467 | .get() 468 | .map(|x| x.as_ptr() as usize) 469 | .unwrap_or(0); 470 | let raw = packed ^ next.map(|x| x.as_ptr() as usize).unwrap_or(0); 471 | NonNull::new(raw as *mut _) 472 | } 473 | 474 | #[inline] 475 | unsafe fn set( 476 | &mut self, 477 | ptr: Self::LinkPtr, 478 | prev: Option, 479 | next: Option, 480 | ) { 481 | let new_packed = prev.map(|x| x.as_ptr() as usize).unwrap_or(0) 482 | ^ next.map(|x| x.as_ptr() as usize).unwrap_or(0); 483 | 484 | let new_next = NonNull::new(new_packed as *mut _); 485 | ptr.as_ref().next_exclusive().set(new_next); 486 | } 487 | 488 | #[inline] 489 | unsafe fn replace_next_or_prev( 490 | &mut self, 491 | ptr: Self::LinkPtr, 492 | old: Option, 493 | new: Option, 494 | ) { 495 | let packed = ptr 496 | .as_ref() 497 | .next_exclusive() 498 | .get() 499 | .map(|x| x.as_ptr() as usize) 500 | .unwrap_or(0); 501 | let new_packed = packed 502 | ^ old.map(|x| x.as_ptr() as usize).unwrap_or(0) 503 | ^ new.map(|x| x.as_ptr() as usize).unwrap_or(0); 504 | 505 | let new_next = NonNull::new(new_packed as *mut _); 506 | ptr.as_ref().next_exclusive().set(new_next); 507 | } 508 | } 509 | 510 | #[inline] 511 | unsafe fn link_between( 512 | link_ops: &mut T, 513 | ptr: T::LinkPtr, 514 | prev: Option, 515 | next: Option, 516 | ) { 517 | if let Some(prev) = prev { 518 | link_ops.set_next(prev, Some(ptr)); 519 | } 520 | if let Some(next) = next { 521 | link_ops.set_prev(next, Some(ptr)); 522 | } 523 | link_ops.set_next(ptr, next); 524 | link_ops.set_prev(ptr, prev); 525 | } 526 | 527 | #[inline] 528 | unsafe fn link_after(link_ops: &mut T, ptr: T::LinkPtr, prev: T::LinkPtr) { 529 | link_between(link_ops, ptr, Some(prev), link_ops.next(prev)); 530 | } 531 | 532 | #[inline] 533 | unsafe fn link_before(link_ops: &mut T, ptr: T::LinkPtr, next: T::LinkPtr) { 534 | link_between(link_ops, ptr, link_ops.prev(next), Some(next)); 535 | } 536 | 537 | #[inline] 538 | unsafe fn replace_with(link_ops: &mut T, ptr: T::LinkPtr, new: T::LinkPtr) { 539 | let prev = link_ops.prev(ptr); 540 | let next = link_ops.next(ptr); 541 | 542 | if let Some(prev) = prev { 543 | link_ops.set_next(prev, Some(new)); 544 | } 545 | if let Some(next) = next { 546 | link_ops.set_prev(next, Some(new)); 547 | } 548 | link_ops.set_next(new, next); 549 | link_ops.set_prev(new, prev); 550 | link_ops.release_link(ptr); 551 | } 552 | 553 | #[inline] 554 | unsafe fn remove(link_ops: &mut T, ptr: T::LinkPtr) { 555 | let prev = link_ops.prev(ptr); 556 | let next = link_ops.next(ptr); 557 | 558 | if let Some(next) = next { 559 | link_ops.set_prev(next, prev); 560 | } 561 | if let Some(prev) = prev { 562 | link_ops.set_next(prev, next); 563 | } 564 | link_ops.release_link(ptr); 565 | } 566 | 567 | #[inline] 568 | unsafe fn splice( 569 | link_ops: &mut T, 570 | start: T::LinkPtr, 571 | end: T::LinkPtr, 572 | prev: Option, 573 | next: Option, 574 | ) { 575 | link_ops.set_prev(start, prev); 576 | link_ops.set_next(end, next); 577 | if let Some(prev) = prev { 578 | link_ops.set_next(prev, Some(start)); 579 | } 580 | if let Some(next) = next { 581 | link_ops.set_prev(next, Some(end)); 582 | } 583 | } 584 | 585 | // ============================================================================= 586 | // Cursor, CursorMut, CursorOwning 587 | // ============================================================================= 588 | 589 | /// A cursor which provides read-only access to a `LinkedList`. 590 | pub struct Cursor<'a, A: Adapter> 591 | where 592 | A::LinkOps: LinkedListOps, 593 | { 594 | current: Option<::LinkPtr>, 595 | list: &'a LinkedList, 596 | } 597 | 598 | impl<'a, A: Adapter> Clone for Cursor<'a, A> 599 | where 600 | A::LinkOps: LinkedListOps, 601 | { 602 | #[inline] 603 | fn clone(&self) -> Cursor<'a, A> { 604 | Cursor { 605 | current: self.current, 606 | list: self.list, 607 | } 608 | } 609 | } 610 | 611 | impl<'a, A: Adapter> Cursor<'a, A> 612 | where 613 | A::LinkOps: LinkedListOps, 614 | { 615 | /// Checks if the cursor is currently pointing to the null object. 616 | #[inline] 617 | pub fn is_null(&self) -> bool { 618 | self.current.is_none() 619 | } 620 | 621 | /// Returns a reference to the object that the cursor is currently 622 | /// pointing to. 623 | /// 624 | /// This returns `None` if the cursor is currently pointing to the null 625 | /// object. 626 | #[inline] 627 | pub fn get(&self) -> Option<&'a ::Value> { 628 | Some(unsafe { &*self.list.adapter.get_value(self.current?) }) 629 | } 630 | 631 | /// Clones and returns the pointer that points to the element that the 632 | /// cursor is referencing. 633 | /// 634 | /// This returns `None` if the cursor is currently pointing to the null 635 | /// object. 636 | #[inline] 637 | pub fn clone_pointer(&self) -> Option<::Pointer> 638 | where 639 | ::Pointer: Clone, 640 | { 641 | let raw_pointer = unsafe { self.list.adapter.get_value(self.current?) }; 642 | Some(unsafe { 643 | crate::pointer_ops::clone_pointer_from_raw(self.list.adapter.pointer_ops(), raw_pointer) 644 | }) 645 | } 646 | 647 | /// Moves the cursor to the next element of the `LinkedList`. 648 | /// 649 | /// If the cursor is pointer to the null object then this will move it to 650 | /// the first element of the `LinkedList`. If it is pointing to the 651 | /// last element of the `LinkedList` then this will move it to the 652 | /// null object. 653 | #[inline] 654 | pub fn move_next(&mut self) { 655 | if let Some(current) = self.current { 656 | self.current = unsafe { self.list.adapter.link_ops().next(current) }; 657 | } else { 658 | self.current = self.list.head; 659 | } 660 | } 661 | 662 | /// Moves the cursor to the previous element of the `LinkedList`. 663 | /// 664 | /// If the cursor is pointer to the null object then this will move it to 665 | /// the last element of the `LinkedList`. If it is pointing to the first 666 | /// element of the `LinkedList` then this will move it to the null object. 667 | #[inline] 668 | pub fn move_prev(&mut self) { 669 | if let Some(current) = self.current { 670 | self.current = unsafe { self.list.adapter.link_ops().prev(current) }; 671 | } else { 672 | self.current = self.list.tail; 673 | } 674 | } 675 | 676 | /// Returns a cursor pointing to the next element of the `LinkedList`. 677 | /// 678 | /// If the cursor is pointer to the null object then this will return the 679 | /// first element of the `LinkedList`. If it is pointing to the last 680 | /// element of the `LinkedList` then this will return a null cursor. 681 | #[inline] 682 | pub fn peek_next(&self) -> Cursor<'_, A> { 683 | let mut next = self.clone(); 684 | next.move_next(); 685 | next 686 | } 687 | 688 | /// Returns a cursor pointing to the previous element of the `LinkedList`. 689 | /// 690 | /// If the cursor is pointer to the null object then this will return the 691 | /// last element of the `LinkedList`. If it is pointing to the first 692 | /// element of the `LinkedList` then this will return a null cursor. 693 | #[inline] 694 | pub fn peek_prev(&self) -> Cursor<'_, A> { 695 | let mut prev = self.clone(); 696 | prev.move_prev(); 697 | prev 698 | } 699 | } 700 | 701 | /// A cursor which provides mutable access to a `LinkedList`. 702 | pub struct CursorMut<'a, A: Adapter> 703 | where 704 | A::LinkOps: LinkedListOps, 705 | { 706 | current: Option<::LinkPtr>, 707 | list: &'a mut LinkedList, 708 | } 709 | 710 | impl<'a, A: Adapter> CursorMut<'a, A> 711 | where 712 | A::LinkOps: LinkedListOps, 713 | { 714 | /// Checks if the cursor is currently pointing to the null object. 715 | #[inline] 716 | pub fn is_null(&self) -> bool { 717 | self.current.is_none() 718 | } 719 | 720 | /// Returns a reference to the object that the cursor is currently 721 | /// pointing to. 722 | /// 723 | /// This returns None if the cursor is currently pointing to the null 724 | /// object. 725 | #[inline] 726 | pub fn get(&self) -> Option<&::Value> { 727 | Some(unsafe { &*self.list.adapter.get_value(self.current?) }) 728 | } 729 | 730 | /// Returns a read-only cursor pointing to the current element. 731 | /// 732 | /// The lifetime of the returned `Cursor` is bound to that of the 733 | /// `CursorMut`, which means it cannot outlive the `CursorMut` and that the 734 | /// `CursorMut` is frozen for the lifetime of the `Cursor`. 735 | #[inline] 736 | pub fn as_cursor(&self) -> Cursor<'_, A> { 737 | Cursor { 738 | current: self.current, 739 | list: self.list, 740 | } 741 | } 742 | 743 | /// Moves the cursor to the next element of the `LinkedList`. 744 | /// 745 | /// If the cursor is pointer to the null object then this will move it to 746 | /// the first element of the `LinkedList`. If it is pointing to the 747 | /// last element of the `LinkedList` then this will move it to the 748 | /// null object. 749 | #[inline] 750 | pub fn move_next(&mut self) { 751 | if let Some(current) = self.current { 752 | self.current = unsafe { self.list.adapter.link_ops().next(current) }; 753 | } else { 754 | self.current = self.list.head; 755 | } 756 | } 757 | 758 | /// Moves the cursor to the previous element of the `LinkedList`. 759 | /// 760 | /// If the cursor is pointer to the null object then this will move it to 761 | /// the last element of the `LinkedList`. If it is pointing to the first 762 | /// element of the `LinkedList` then this will move it to the null object. 763 | #[inline] 764 | pub fn move_prev(&mut self) { 765 | if let Some(current) = self.current { 766 | self.current = unsafe { self.list.adapter.link_ops().prev(current) }; 767 | } else { 768 | self.current = self.list.tail; 769 | } 770 | } 771 | 772 | ///Returns a cursor pointing to the next element of the `LinkedList`. 773 | /// 774 | /// If the cursor is pointer to the null object then this will return the 775 | /// first element of the `LinkedList`. If it is pointing to the last 776 | /// element of the `LinkedList` then this will return a null cursor. 777 | #[inline] 778 | pub fn peek_next(&self) -> Cursor<'_, A> { 779 | let mut next = self.as_cursor(); 780 | next.move_next(); 781 | next 782 | } 783 | 784 | /// Returns a cursor pointing to the previous element of the `LinkedList`. 785 | /// 786 | /// If the cursor is pointer to the null object then this will return the 787 | /// last element of the `LinkedList`. If it is pointing to the first 788 | /// element of the `LinkedList` then this will return a null cursor. 789 | #[inline] 790 | pub fn peek_prev(&self) -> Cursor<'_, A> { 791 | let mut prev = self.as_cursor(); 792 | prev.move_prev(); 793 | prev 794 | } 795 | 796 | /// Removes the current element from the `LinkedList`. 797 | /// 798 | /// A pointer to the element that was removed is returned, and the cursor is 799 | /// moved to point to the next element in the `LinkedList`. 800 | /// 801 | /// If the cursor is currently pointing to the null object then no element 802 | /// is removed and `None` is returned. 803 | #[inline] 804 | pub fn remove(&mut self) -> Option<::Pointer> { 805 | unsafe { 806 | if let Some(current) = self.current { 807 | if self.list.head == self.current { 808 | self.list.head = self.list.adapter.link_ops().next(current); 809 | } 810 | if self.list.tail == self.current { 811 | self.list.tail = self.list.adapter.link_ops().prev(current); 812 | } 813 | let next = self.list.adapter.link_ops().next(current); 814 | let result = current; 815 | remove(self.list.adapter.link_ops_mut(), current); 816 | self.current = next; 817 | Some( 818 | self.list 819 | .adapter 820 | .pointer_ops() 821 | .from_raw(self.list.adapter.get_value(result)), 822 | ) 823 | } else { 824 | None 825 | } 826 | } 827 | } 828 | 829 | /// Removes the current element from the `LinkedList` and inserts another 830 | /// object in its place. 831 | /// 832 | /// A pointer to the element that was removed is returned, and the cursor is 833 | /// modified to point to the newly added element. 834 | /// 835 | /// If the cursor is currently pointing to the null object then an error is 836 | /// returned containing the given `val` parameter. 837 | /// 838 | /// # Panics 839 | /// 840 | /// Panics if the new element is already linked to a different intrusive 841 | /// collection. 842 | #[inline] 843 | pub fn replace_with( 844 | &mut self, 845 | val: ::Pointer, 846 | ) -> Result<::Pointer, ::Pointer> 847 | { 848 | unsafe { 849 | if let Some(current) = self.current { 850 | let new = self.list.node_from_value(val); 851 | if self.list.head == self.current { 852 | self.list.head = Some(new); 853 | } 854 | if self.list.tail == self.current { 855 | self.list.tail = Some(new); 856 | } 857 | let result = current; 858 | replace_with(self.list.adapter.link_ops_mut(), current, new); 859 | self.current = Some(new); 860 | Ok(self 861 | .list 862 | .adapter 863 | .pointer_ops() 864 | .from_raw(self.list.adapter.get_value(result))) 865 | } else { 866 | Err(val) 867 | } 868 | } 869 | } 870 | 871 | /// Inserts a new element into the `LinkedList` after the current one. 872 | /// 873 | /// If the cursor is pointing at the null object then the new element is 874 | /// inserted at the front of the `LinkedList`. 875 | /// 876 | /// # Panics 877 | /// 878 | /// Panics if the new element is already linked to a different intrusive 879 | /// collection. 880 | #[inline] 881 | pub fn insert_after(&mut self, val: ::Pointer) { 882 | unsafe { 883 | let new = self.list.node_from_value(val); 884 | if let Some(current) = self.current { 885 | link_after(self.list.adapter.link_ops_mut(), new, current); 886 | } else { 887 | link_between(self.list.adapter.link_ops_mut(), new, None, self.list.head); 888 | self.list.head = Some(new); 889 | } 890 | if self.list.tail == self.current { 891 | self.list.tail = Some(new); 892 | } 893 | } 894 | } 895 | 896 | /// Inserts a new element into the `LinkedList` before the current one. 897 | /// 898 | /// If the cursor is pointing at the null object then the new element is 899 | /// inserted at the end of the `LinkedList`. 900 | /// 901 | /// # Panics 902 | /// 903 | /// Panics if the new element is already linked to a different intrusive 904 | /// collection. 905 | #[inline] 906 | pub fn insert_before(&mut self, val: ::Pointer) { 907 | unsafe { 908 | let new = self.list.node_from_value(val); 909 | 910 | let link_ops = self.list.adapter.link_ops_mut(); 911 | 912 | if let Some(current) = self.current { 913 | link_before(link_ops, new, current); 914 | } else { 915 | link_between(link_ops, new, self.list.tail, None); 916 | self.list.tail = Some(new); 917 | } 918 | if self.list.head == self.current { 919 | self.list.head = Some(new); 920 | } 921 | } 922 | } 923 | 924 | /// Inserts the elements from the given `LinkedList` after the current one. 925 | /// 926 | /// If the cursor is pointing at the null object then the new elements are 927 | /// inserted at the start of the `LinkedList`. 928 | #[inline] 929 | pub fn splice_after(&mut self, mut list: LinkedList) { 930 | if !list.is_empty() { 931 | unsafe { 932 | let head = list.head.unwrap_unchecked(); 933 | let tail = list.tail.unwrap_unchecked(); 934 | 935 | let link_ops = self.list.adapter.link_ops_mut(); 936 | 937 | if let Some(current) = self.current { 938 | splice(link_ops, head, tail, Some(current), link_ops.next(current)); 939 | } else { 940 | splice(link_ops, head, tail, None, self.list.head); 941 | self.list.head = list.head; 942 | } 943 | if self.list.tail == self.current { 944 | self.list.tail = list.tail; 945 | } 946 | list.head = None; 947 | list.tail = None; 948 | } 949 | } 950 | } 951 | 952 | /// Moves all element from the given `LinkedList` before the current one. 953 | /// 954 | /// If the cursor is pointing at the null object then the new elements are 955 | /// inserted at the end of the `LinkedList`. 956 | #[inline] 957 | pub fn splice_before(&mut self, mut list: LinkedList) { 958 | if !list.is_empty() { 959 | unsafe { 960 | let head = list.head.unwrap_unchecked(); 961 | let tail = list.tail.unwrap_unchecked(); 962 | 963 | let link_ops = self.list.adapter.link_ops_mut(); 964 | 965 | if let Some(current) = self.current { 966 | splice(link_ops, head, tail, link_ops.prev(current), Some(current)); 967 | } else { 968 | splice(link_ops, head, tail, self.list.tail, None); 969 | self.list.tail = list.tail; 970 | } 971 | if self.list.head == self.current { 972 | self.list.head = list.head; 973 | } 974 | list.head = None; 975 | list.tail = None; 976 | } 977 | } 978 | } 979 | 980 | /// Splits the list into two after the current element. This will return a 981 | /// new list consisting of everything after the cursor, with the original 982 | /// list retaining everything before. 983 | /// 984 | /// If the cursor is pointing at the null object then the entire contents 985 | /// of the `LinkedList` are moved. 986 | #[inline] 987 | pub fn split_after(&mut self) -> LinkedList 988 | where 989 | A: Clone, 990 | { 991 | if let Some(current) = self.current { 992 | unsafe { 993 | let mut list = LinkedList { 994 | head: self.list.adapter.link_ops().next(current), 995 | tail: self.list.tail, 996 | adapter: self.list.adapter.clone(), 997 | }; 998 | if let Some(head) = list.head { 999 | self.list.adapter.link_ops_mut().set_prev(head, None); 1000 | } else { 1001 | list.tail = None; 1002 | } 1003 | self.list.adapter.link_ops_mut().set_next(current, None); 1004 | self.list.tail = self.current; 1005 | list 1006 | } 1007 | } else { 1008 | let list = LinkedList { 1009 | head: self.list.head, 1010 | tail: self.list.tail, 1011 | adapter: self.list.adapter.clone(), 1012 | }; 1013 | self.list.head = None; 1014 | self.list.tail = None; 1015 | list 1016 | } 1017 | } 1018 | 1019 | /// Splits the list into two before the current element. This will return a 1020 | /// new list consisting of everything before the cursor, with the original 1021 | /// list retaining everything after. 1022 | /// 1023 | /// If the cursor is pointing at the null object then the entire contents 1024 | /// of the `LinkedList` are moved. 1025 | #[inline] 1026 | pub fn split_before(&mut self) -> LinkedList 1027 | where 1028 | A: Clone, 1029 | { 1030 | if let Some(current) = self.current { 1031 | unsafe { 1032 | let mut list = LinkedList { 1033 | head: self.list.head, 1034 | tail: self.list.adapter.link_ops().prev(current), 1035 | adapter: self.list.adapter.clone(), 1036 | }; 1037 | if let Some(tail) = list.tail { 1038 | self.list.adapter.link_ops_mut().set_prev(tail, None); 1039 | } else { 1040 | list.head = None; 1041 | } 1042 | self.list.adapter.link_ops_mut().set_prev(current, None); 1043 | self.list.head = self.current; 1044 | list 1045 | } 1046 | } else { 1047 | let list = LinkedList { 1048 | head: self.list.head, 1049 | tail: self.list.tail, 1050 | adapter: self.list.adapter.clone(), 1051 | }; 1052 | self.list.head = None; 1053 | self.list.tail = None; 1054 | list 1055 | } 1056 | } 1057 | 1058 | /// Consumes `CursorMut` and returns a reference to the object that 1059 | /// the cursor is currently pointing to. Unlike [get](Self::get), 1060 | /// the returned reference's lifetime is tied to `LinkedList`'s lifetime. 1061 | /// 1062 | /// This returns None if the cursor is currently pointing to the null object. 1063 | #[inline] 1064 | pub fn into_ref(self) -> Option<&'a ::Value> { 1065 | Some(unsafe { &*self.list.adapter.get_value(self.current?) }) 1066 | } 1067 | } 1068 | 1069 | /// A cursor with ownership over the `LinkedList` it points into. 1070 | pub struct CursorOwning 1071 | where 1072 | A::LinkOps: LinkedListOps, 1073 | { 1074 | current: Option<::LinkPtr>, 1075 | list: LinkedList, 1076 | } 1077 | 1078 | impl CursorOwning 1079 | where 1080 | A::LinkOps: LinkedListOps, 1081 | { 1082 | /// Consumes self and returns the inner `LinkedList`. 1083 | #[inline] 1084 | pub fn into_inner(self) -> LinkedList { 1085 | self.list 1086 | } 1087 | 1088 | /// Returns a read-only cursor pointing to the current element. 1089 | /// 1090 | /// The lifetime of the returned `Cursor` is bound to that of the 1091 | /// `CursorOwning`, which means it cannot outlive the `CursorOwning` and that the 1092 | /// `CursorOwning` is frozen for the lifetime of the `Cursor`. 1093 | /// 1094 | /// Mutations of the returned cursor are _not_ reflected in the original. 1095 | #[inline] 1096 | pub fn as_cursor(&self) -> Cursor<'_, A> { 1097 | Cursor { 1098 | current: self.current, 1099 | list: &self.list, 1100 | } 1101 | } 1102 | 1103 | /// Perform action with mutable reference to the cursor. 1104 | /// 1105 | /// All mutations of the cursor are reflected in the original. 1106 | #[inline] 1107 | pub fn with_cursor_mut(&mut self, f: impl FnOnce(&mut CursorMut<'_, A>) -> T) -> T { 1108 | let mut cursor = CursorMut { 1109 | current: self.current, 1110 | list: &mut self.list, 1111 | }; 1112 | let ret = f(&mut cursor); 1113 | self.current = cursor.current; 1114 | ret 1115 | } 1116 | } 1117 | unsafe impl Send for CursorOwning 1118 | where 1119 | LinkedList: Send, 1120 | A::LinkOps: LinkedListOps, 1121 | { 1122 | } 1123 | 1124 | // ============================================================================= 1125 | // LinkedList 1126 | // ============================================================================= 1127 | 1128 | /// An intrusive doubly-linked list. 1129 | /// 1130 | /// When this collection is dropped, all elements linked into it will be 1131 | /// converted back to owned pointers and dropped. 1132 | pub struct LinkedList 1133 | where 1134 | A::LinkOps: LinkedListOps, 1135 | { 1136 | head: Option<::LinkPtr>, 1137 | tail: Option<::LinkPtr>, 1138 | adapter: A, 1139 | } 1140 | 1141 | impl LinkedList 1142 | where 1143 | A::LinkOps: LinkedListOps, 1144 | { 1145 | #[inline] 1146 | fn node_from_value( 1147 | &mut self, 1148 | val: ::Pointer, 1149 | ) -> ::LinkPtr { 1150 | use link_ops::LinkOps; 1151 | 1152 | unsafe { 1153 | let raw = self.adapter.pointer_ops().into_raw(val); 1154 | let link = self.adapter.get_link(raw); 1155 | 1156 | if !self.adapter.link_ops_mut().acquire_link(link) { 1157 | // convert the node back into a pointer 1158 | self.adapter.pointer_ops().from_raw(raw); 1159 | 1160 | panic!("attempted to insert an object that is already linked"); 1161 | } 1162 | 1163 | link 1164 | } 1165 | } 1166 | 1167 | /// Creates an empty `LinkedList`. 1168 | #[cfg(not(feature = "nightly"))] 1169 | #[inline] 1170 | pub fn new(adapter: A) -> LinkedList { 1171 | LinkedList { 1172 | head: None, 1173 | tail: None, 1174 | adapter, 1175 | } 1176 | } 1177 | 1178 | /// Creates an empty `LinkedList`. 1179 | #[cfg(feature = "nightly")] 1180 | #[inline] 1181 | pub const fn new(adapter: A) -> LinkedList { 1182 | LinkedList { 1183 | head: None, 1184 | tail: None, 1185 | adapter, 1186 | } 1187 | } 1188 | 1189 | /// Returns `true` if the `LinkedList` is empty. 1190 | #[inline] 1191 | pub fn is_empty(&self) -> bool { 1192 | self.head.is_none() 1193 | } 1194 | 1195 | /// Returns a null `Cursor` for this list. 1196 | #[inline] 1197 | pub fn cursor(&self) -> Cursor<'_, A> { 1198 | Cursor { 1199 | current: None, 1200 | list: self, 1201 | } 1202 | } 1203 | 1204 | /// Returns a null `CursorMut` for this list. 1205 | #[inline] 1206 | pub fn cursor_mut(&mut self) -> CursorMut<'_, A> { 1207 | CursorMut { 1208 | current: None, 1209 | list: self, 1210 | } 1211 | } 1212 | 1213 | /// Returns a null `CursorOwning` for this list. 1214 | #[inline] 1215 | pub fn cursor_owning(self) -> CursorOwning { 1216 | CursorOwning { 1217 | current: None, 1218 | list: self, 1219 | } 1220 | } 1221 | 1222 | /// Creates a `Cursor` from a pointer to an element. 1223 | /// 1224 | /// # Safety 1225 | /// 1226 | /// `ptr` must be a pointer to an object that is part of this list. 1227 | #[inline] 1228 | pub unsafe fn cursor_from_ptr( 1229 | &self, 1230 | ptr: *const ::Value, 1231 | ) -> Cursor<'_, A> { 1232 | Cursor { 1233 | current: Some(self.adapter.get_link(ptr)), 1234 | list: self, 1235 | } 1236 | } 1237 | 1238 | /// Creates a `CursorMut` from a pointer to an element. 1239 | /// 1240 | /// # Safety 1241 | /// 1242 | /// `ptr` must be a pointer to an object that is part of this list. 1243 | #[inline] 1244 | pub unsafe fn cursor_mut_from_ptr( 1245 | &mut self, 1246 | ptr: *const ::Value, 1247 | ) -> CursorMut<'_, A> { 1248 | CursorMut { 1249 | current: Some(self.adapter.get_link(ptr)), 1250 | list: self, 1251 | } 1252 | } 1253 | 1254 | /// Creates a `CursorOwning` from a pointer to an element. 1255 | /// 1256 | /// # Safety 1257 | /// 1258 | /// `ptr` must be a pointer to an object that is part of this list. 1259 | #[inline] 1260 | pub unsafe fn cursor_owning_from_ptr( 1261 | self, 1262 | ptr: *const ::Value, 1263 | ) -> CursorOwning { 1264 | CursorOwning { 1265 | current: Some(self.adapter.get_link(ptr)), 1266 | list: self, 1267 | } 1268 | } 1269 | 1270 | /// Returns a `Cursor` pointing to the first element of the list. If the 1271 | /// list is empty then a null cursor is returned. 1272 | #[inline] 1273 | pub fn front(&self) -> Cursor<'_, A> { 1274 | let mut cursor = self.cursor(); 1275 | cursor.move_next(); 1276 | cursor 1277 | } 1278 | 1279 | /// Returns a `CursorMut` pointing to the first element of the list. If the 1280 | /// the list is empty then a null cursor is returned. 1281 | #[inline] 1282 | pub fn front_mut(&mut self) -> CursorMut<'_, A> { 1283 | let mut cursor = self.cursor_mut(); 1284 | cursor.move_next(); 1285 | cursor 1286 | } 1287 | 1288 | /// Returns a `CursorOwning` pointing to the first element of the list. If the 1289 | /// the list is empty then a null cursor is returned. 1290 | #[inline] 1291 | pub fn front_owning(self) -> CursorOwning { 1292 | let mut cursor = self.cursor_owning(); 1293 | cursor.with_cursor_mut(|c| c.move_next()); 1294 | cursor 1295 | } 1296 | 1297 | /// Returns a `Cursor` pointing to the last element of the list. If the list 1298 | /// is empty then a null cursor is returned. 1299 | #[inline] 1300 | pub fn back(&self) -> Cursor<'_, A> { 1301 | let mut cursor = self.cursor(); 1302 | cursor.move_prev(); 1303 | cursor 1304 | } 1305 | 1306 | /// Returns a `CursorMut` pointing to the last element of the list. If the 1307 | /// list is empty then a null cursor is returned. 1308 | #[inline] 1309 | pub fn back_mut(&mut self) -> CursorMut<'_, A> { 1310 | let mut cursor = self.cursor_mut(); 1311 | cursor.move_prev(); 1312 | cursor 1313 | } 1314 | 1315 | /// Returns a `CursorOwning` pointing to the last element of the list. If the 1316 | /// list is empty then a null cursor is returned. 1317 | #[inline] 1318 | pub fn back_owning(self) -> CursorOwning { 1319 | let mut cursor = self.cursor_owning(); 1320 | cursor.with_cursor_mut(|c| c.move_prev()); 1321 | cursor 1322 | } 1323 | 1324 | /// Gets an iterator over the objects in the `LinkedList`. 1325 | #[inline] 1326 | pub fn iter(&self) -> Iter<'_, A> { 1327 | Iter { 1328 | head: self.head, 1329 | tail: self.tail, 1330 | list: self, 1331 | } 1332 | } 1333 | 1334 | /// Removes all elements from the `LinkedList`. 1335 | /// 1336 | /// This will unlink all object currently in the list, which requires 1337 | /// iterating through all elements in the `LinkedList`. Each element is 1338 | /// converted back to an owned pointer and then dropped. 1339 | #[inline] 1340 | pub fn clear(&mut self) { 1341 | use link_ops::LinkOps; 1342 | 1343 | let mut current = self.head; 1344 | self.head = None; 1345 | self.tail = None; 1346 | while let Some(x) = current { 1347 | unsafe { 1348 | let next = self.adapter.link_ops().next(x); 1349 | self.adapter.link_ops_mut().release_link(x); 1350 | self.adapter 1351 | .pointer_ops() 1352 | .from_raw(self.adapter.get_value(x)); 1353 | current = next; 1354 | } 1355 | } 1356 | } 1357 | 1358 | /// Empties the `LinkedList` without unlinking or freeing objects in it. 1359 | /// 1360 | /// Since this does not unlink any objects, any attempts to link these 1361 | /// objects into another `LinkedList` will fail but will not cause any 1362 | /// memory unsafety. To unlink those objects manually, you must call the 1363 | /// `force_unlink` function on them. 1364 | #[inline] 1365 | pub fn fast_clear(&mut self) { 1366 | self.head = None; 1367 | self.tail = None; 1368 | } 1369 | 1370 | /// Takes all the elements out of the `LinkedList`, leaving it empty. 1371 | /// The taken elements are returned as a new `LinkedList`. 1372 | #[inline] 1373 | pub fn take(&mut self) -> LinkedList 1374 | where 1375 | A: Clone, 1376 | { 1377 | let list = LinkedList { 1378 | head: self.head, 1379 | tail: self.tail, 1380 | adapter: self.adapter.clone(), 1381 | }; 1382 | self.head = None; 1383 | self.tail = None; 1384 | list 1385 | } 1386 | 1387 | /// Inserts a new element at the start of the `LinkedList`. 1388 | #[inline] 1389 | pub fn push_front(&mut self, val: ::Pointer) { 1390 | self.cursor_mut().insert_after(val); 1391 | } 1392 | 1393 | /// Inserts a new element at the end of the `LinkedList`. 1394 | #[inline] 1395 | pub fn push_back(&mut self, val: ::Pointer) { 1396 | self.cursor_mut().insert_before(val); 1397 | } 1398 | 1399 | /// Removes the first element of the `LinkedList`. 1400 | /// 1401 | /// This returns `None` if the `LinkedList` is empty. 1402 | #[inline] 1403 | pub fn pop_front(&mut self) -> Option<::Pointer> { 1404 | self.front_mut().remove() 1405 | } 1406 | 1407 | /// Removes the last element of the `LinkedList`. 1408 | /// 1409 | /// This returns `None` if the `LinkedList` is empty. 1410 | #[inline] 1411 | pub fn pop_back(&mut self) -> Option<::Pointer> { 1412 | self.back_mut().remove() 1413 | } 1414 | } 1415 | 1416 | // Allow read-only access to values from multiple threads 1417 | unsafe impl Sync for LinkedList 1418 | where 1419 | ::Value: Sync, 1420 | A::LinkOps: LinkedListOps, 1421 | { 1422 | } 1423 | 1424 | // Allow sending to another thread if the ownership (represented by the ::Pointer owned 1425 | // pointer type) can be transferred to another thread. 1426 | unsafe impl Send for LinkedList 1427 | where 1428 | ::Pointer: Send, 1429 | A::LinkOps: LinkedListOps, 1430 | { 1431 | } 1432 | 1433 | // Drop all owned pointers if the collection is dropped 1434 | impl Drop for LinkedList 1435 | where 1436 | A::LinkOps: LinkedListOps, 1437 | { 1438 | #[inline] 1439 | fn drop(&mut self) { 1440 | self.clear(); 1441 | } 1442 | } 1443 | 1444 | impl IntoIterator for LinkedList 1445 | where 1446 | A::LinkOps: LinkedListOps, 1447 | { 1448 | type Item = ::Pointer; 1449 | type IntoIter = IntoIter; 1450 | 1451 | #[inline] 1452 | fn into_iter(self) -> IntoIter { 1453 | IntoIter { list: self } 1454 | } 1455 | } 1456 | 1457 | impl<'a, A: Adapter + 'a> IntoIterator for &'a LinkedList 1458 | where 1459 | A::LinkOps: LinkedListOps, 1460 | { 1461 | type Item = &'a ::Value; 1462 | type IntoIter = Iter<'a, A>; 1463 | 1464 | #[inline] 1465 | fn into_iter(self) -> Iter<'a, A> { 1466 | self.iter() 1467 | } 1468 | } 1469 | 1470 | impl Default for LinkedList 1471 | where 1472 | A::LinkOps: LinkedListOps, 1473 | { 1474 | fn default() -> LinkedList { 1475 | LinkedList::new(A::default()) 1476 | } 1477 | } 1478 | 1479 | impl fmt::Debug for LinkedList 1480 | where 1481 | A::LinkOps: LinkedListOps, 1482 | ::Value: fmt::Debug, 1483 | { 1484 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 1485 | f.debug_list().entries(self.iter()).finish() 1486 | } 1487 | } 1488 | 1489 | // ============================================================================= 1490 | // Iter 1491 | // ============================================================================= 1492 | 1493 | /// An iterator over references to the items of a `LinkedList`. 1494 | pub struct Iter<'a, A: Adapter> 1495 | where 1496 | A::LinkOps: LinkedListOps, 1497 | { 1498 | head: Option<::LinkPtr>, 1499 | tail: Option<::LinkPtr>, 1500 | list: &'a LinkedList, 1501 | } 1502 | impl<'a, A: Adapter + 'a> Iterator for Iter<'a, A> 1503 | where 1504 | A::LinkOps: LinkedListOps, 1505 | { 1506 | type Item = &'a ::Value; 1507 | 1508 | #[inline] 1509 | fn next(&mut self) -> Option<&'a ::Value> { 1510 | let head = self.head?; 1511 | 1512 | if Some(head) == self.tail { 1513 | self.head = None; 1514 | self.tail = None; 1515 | } else { 1516 | self.head = unsafe { self.list.adapter.link_ops().next(head) }; 1517 | } 1518 | Some(unsafe { &*self.list.adapter.get_value(head) }) 1519 | } 1520 | } 1521 | impl<'a, A: Adapter + 'a> DoubleEndedIterator for Iter<'a, A> 1522 | where 1523 | A::LinkOps: LinkedListOps, 1524 | { 1525 | #[inline] 1526 | fn next_back(&mut self) -> Option<&'a ::Value> { 1527 | let tail = self.tail?; 1528 | 1529 | if Some(tail) == self.head { 1530 | self.head = None; 1531 | self.tail = None; 1532 | } else { 1533 | self.tail = unsafe { self.list.adapter.link_ops().prev(tail) }; 1534 | } 1535 | Some(unsafe { &*self.list.adapter.get_value(tail) }) 1536 | } 1537 | } 1538 | impl<'a, A: Adapter + 'a> Clone for Iter<'a, A> 1539 | where 1540 | A::LinkOps: LinkedListOps, 1541 | { 1542 | #[inline] 1543 | fn clone(&self) -> Iter<'a, A> { 1544 | Iter { 1545 | head: self.head, 1546 | tail: self.tail, 1547 | list: self.list, 1548 | } 1549 | } 1550 | } 1551 | 1552 | // ============================================================================= 1553 | // IntoIter 1554 | // ============================================================================= 1555 | 1556 | /// An iterator which consumes a `LinkedList`. 1557 | pub struct IntoIter 1558 | where 1559 | A::LinkOps: LinkedListOps, 1560 | { 1561 | list: LinkedList, 1562 | } 1563 | impl Iterator for IntoIter 1564 | where 1565 | A::LinkOps: LinkedListOps, 1566 | { 1567 | type Item = ::Pointer; 1568 | 1569 | #[inline] 1570 | fn next(&mut self) -> Option<::Pointer> { 1571 | self.list.pop_front() 1572 | } 1573 | } 1574 | impl DoubleEndedIterator for IntoIter 1575 | where 1576 | A::LinkOps: LinkedListOps, 1577 | { 1578 | #[inline] 1579 | fn next_back(&mut self) -> Option<::Pointer> { 1580 | self.list.pop_back() 1581 | } 1582 | } 1583 | 1584 | // ============================================================================= 1585 | // Tests 1586 | // ============================================================================= 1587 | 1588 | #[cfg(test)] 1589 | mod tests { 1590 | use alloc::boxed::Box; 1591 | 1592 | use crate::UnsafeRef; 1593 | 1594 | use super::{CursorOwning, Link, LinkedList}; 1595 | use std::fmt; 1596 | use std::format; 1597 | use std::rc::Rc; 1598 | use std::vec::Vec; 1599 | 1600 | struct Obj { 1601 | link1: Link, 1602 | link2: Link, 1603 | value: u32, 1604 | } 1605 | impl fmt::Debug for Obj { 1606 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 1607 | write!(f, "{}", self.value) 1608 | } 1609 | } 1610 | intrusive_adapter!(ObjAdapter1 = Rc: Obj { link1: Link }); 1611 | intrusive_adapter!(ObjAdapter2 = Rc: Obj { link2: Link }); 1612 | intrusive_adapter!(UnsafeRefObjAdapter1 = UnsafeRef: Obj { link1: Link }); 1613 | 1614 | fn make_rc_obj(value: u32) -> Rc { 1615 | Rc::new(make_obj(value)) 1616 | } 1617 | 1618 | fn make_obj(value: u32) -> Obj { 1619 | Obj { 1620 | link1: Link::new(), 1621 | link2: Link::default(), 1622 | value, 1623 | } 1624 | } 1625 | 1626 | #[test] 1627 | fn test_link() { 1628 | let a = make_rc_obj(1); 1629 | assert!(!a.link1.is_linked()); 1630 | assert!(!a.link2.is_linked()); 1631 | 1632 | let mut b = LinkedList::::default(); 1633 | assert!(b.is_empty()); 1634 | 1635 | b.cursor_mut().insert_after(a.clone()); 1636 | assert!(!b.is_empty()); 1637 | assert!(a.link1.is_linked()); 1638 | assert!(!a.link2.is_linked()); 1639 | assert_eq!(format!("{:?}", a.link1), "linked"); 1640 | assert_eq!(format!("{:?}", a.link2), "unlinked"); 1641 | 1642 | assert_eq!( 1643 | b.front_mut().remove().unwrap().as_ref() as *const _, 1644 | a.as_ref() as *const _ 1645 | ); 1646 | assert!(b.is_empty()); 1647 | assert!(!a.link1.is_linked()); 1648 | assert!(!a.link2.is_linked()); 1649 | } 1650 | 1651 | #[test] 1652 | fn test_cursor() { 1653 | let a = make_rc_obj(1); 1654 | let b = make_rc_obj(2); 1655 | let c = make_rc_obj(3); 1656 | 1657 | let mut l = LinkedList::new(ObjAdapter1::new()); 1658 | let mut cur = l.cursor_mut(); 1659 | assert!(cur.is_null()); 1660 | assert!(cur.get().is_none()); 1661 | assert!(cur.remove().is_none()); 1662 | assert_eq!( 1663 | cur.replace_with(a.clone()).unwrap_err().as_ref() as *const _, 1664 | a.as_ref() as *const _ 1665 | ); 1666 | 1667 | cur.insert_before(a.clone()); 1668 | cur.insert_before(c.clone()); 1669 | cur.move_prev(); 1670 | cur.insert_before(b.clone()); 1671 | assert!(cur.peek_next().is_null()); 1672 | cur.move_next(); 1673 | assert!(cur.is_null()); 1674 | 1675 | cur.move_next(); 1676 | assert!(cur.peek_prev().is_null()); 1677 | assert!(!cur.is_null()); 1678 | assert_eq!(cur.get().unwrap() as *const _, a.as_ref() as *const _); 1679 | 1680 | { 1681 | let mut cur2 = cur.as_cursor(); 1682 | assert_eq!(cur2.get().unwrap() as *const _, a.as_ref() as *const _); 1683 | assert_eq!(cur2.peek_next().get().unwrap().value, 2); 1684 | cur2.move_next(); 1685 | assert_eq!(cur2.get().unwrap().value, 2); 1686 | cur2.move_next(); 1687 | assert_eq!(cur2.peek_prev().get().unwrap().value, 2); 1688 | assert_eq!(cur2.get().unwrap() as *const _, c.as_ref() as *const _); 1689 | cur2.move_prev(); 1690 | assert_eq!(cur2.get().unwrap() as *const _, b.as_ref() as *const _); 1691 | cur2.move_next(); 1692 | assert_eq!(cur2.get().unwrap() as *const _, c.as_ref() as *const _); 1693 | cur2.move_next(); 1694 | assert!(cur2.is_null()); 1695 | assert!(cur2.clone().get().is_none()); 1696 | } 1697 | assert_eq!(cur.get().unwrap() as *const _, a.as_ref() as *const _); 1698 | 1699 | cur.move_next(); 1700 | assert_eq!( 1701 | cur.remove().unwrap().as_ref() as *const _, 1702 | b.as_ref() as *const _ 1703 | ); 1704 | assert_eq!(cur.get().unwrap() as *const _, c.as_ref() as *const _); 1705 | cur.insert_after(b.clone()); 1706 | assert_eq!(cur.get().unwrap() as *const _, c.as_ref() as *const _); 1707 | cur.move_prev(); 1708 | assert_eq!(cur.get().unwrap() as *const _, a.as_ref() as *const _); 1709 | assert_eq!( 1710 | cur.remove().unwrap().as_ref() as *const _, 1711 | a.as_ref() as *const _ 1712 | ); 1713 | assert!(!a.link1.is_linked()); 1714 | assert!(c.link1.is_linked()); 1715 | assert_eq!(cur.get().unwrap() as *const _, c.as_ref() as *const _); 1716 | assert_eq!( 1717 | cur.replace_with(a.clone()).unwrap().as_ref() as *const _, 1718 | c.as_ref() as *const _ 1719 | ); 1720 | assert!(a.link1.is_linked()); 1721 | assert!(!c.link1.is_linked()); 1722 | assert_eq!(cur.get().unwrap() as *const _, a.as_ref() as *const _); 1723 | cur.move_next(); 1724 | assert_eq!( 1725 | cur.replace_with(c.clone()).unwrap().as_ref() as *const _, 1726 | b.as_ref() as *const _ 1727 | ); 1728 | assert!(a.link1.is_linked()); 1729 | assert!(!b.link1.is_linked()); 1730 | assert!(c.link1.is_linked()); 1731 | assert_eq!(cur.get().unwrap() as *const _, c.as_ref() as *const _); 1732 | } 1733 | 1734 | #[test] 1735 | fn test_cursor_owning() { 1736 | struct Container { 1737 | cur: CursorOwning, 1738 | } 1739 | 1740 | let mut l = LinkedList::new(ObjAdapter1::new()); 1741 | l.push_back(make_rc_obj(1)); 1742 | l.push_back(make_rc_obj(2)); 1743 | l.push_back(make_rc_obj(3)); 1744 | l.push_back(make_rc_obj(4)); 1745 | let mut con = Container { 1746 | cur: l.cursor_owning(), 1747 | }; 1748 | assert!(con.cur.as_cursor().is_null()); 1749 | 1750 | con.cur = con.cur.into_inner().front_owning(); 1751 | assert_eq!(con.cur.as_cursor().get().unwrap().value, 1); 1752 | 1753 | con.cur.with_cursor_mut(|c| c.move_next()); 1754 | assert_eq!(con.cur.as_cursor().get().unwrap().value, 2); 1755 | 1756 | con.cur = con.cur.into_inner().back_owning(); 1757 | assert_eq!(con.cur.as_cursor().get().unwrap().value, 4); 1758 | } 1759 | 1760 | #[test] 1761 | fn test_push_pop() { 1762 | let a = make_rc_obj(1); 1763 | let b = make_rc_obj(2); 1764 | let c = make_rc_obj(3); 1765 | 1766 | let mut l = LinkedList::new(ObjAdapter1::new()); 1767 | l.push_front(a); 1768 | assert_eq!(l.iter().map(|x| x.value).collect::>(), [1]); 1769 | l.push_front(b); 1770 | assert_eq!(l.iter().map(|x| x.value).collect::>(), [2, 1]); 1771 | l.push_back(c); 1772 | assert_eq!(l.iter().map(|x| x.value).collect::>(), [2, 1, 3]); 1773 | assert_eq!(l.pop_front().unwrap().value, 2); 1774 | assert_eq!(l.iter().map(|x| x.value).collect::>(), [1, 3]); 1775 | assert_eq!(l.pop_back().unwrap().value, 3); 1776 | assert_eq!(l.iter().map(|x| x.value).collect::>(), [1]); 1777 | assert_eq!(l.pop_front().unwrap().value, 1); 1778 | assert_eq!(l.iter().map(|x| x.value).collect::>(), []); 1779 | assert!(l.pop_front().is_none()); 1780 | assert_eq!(l.iter().map(|x| x.value).collect::>(), []); 1781 | assert!(l.pop_back().is_none()); 1782 | assert_eq!(l.iter().map(|x| x.value).collect::>(), []); 1783 | } 1784 | 1785 | #[test] 1786 | fn test_split_splice() { 1787 | let mut l1 = LinkedList::new(ObjAdapter1::new()); 1788 | let mut l2 = LinkedList::new(ObjAdapter1::new()); 1789 | let mut l3 = LinkedList::new(ObjAdapter1::new()); 1790 | 1791 | let a = make_rc_obj(1); 1792 | let b = make_rc_obj(2); 1793 | let c = make_rc_obj(3); 1794 | let d = make_rc_obj(4); 1795 | l1.cursor_mut().insert_before(a); 1796 | l1.cursor_mut().insert_before(b); 1797 | l1.cursor_mut().insert_before(c); 1798 | l1.cursor_mut().insert_before(d); 1799 | assert_eq!(l1.iter().map(|x| x.value).collect::>(), [1, 2, 3, 4]); 1800 | assert_eq!(l2.iter().map(|x| x.value).collect::>(), []); 1801 | assert_eq!(l3.iter().map(|x| x.value).collect::>(), []); 1802 | { 1803 | let mut cur = l1.front_mut(); 1804 | cur.move_next(); 1805 | l2 = cur.split_after(); 1806 | } 1807 | assert_eq!(l1.iter().map(|x| x.value).collect::>(), [1, 2]); 1808 | assert_eq!(l2.iter().map(|x| x.value).collect::>(), [3, 4]); 1809 | assert_eq!(l3.iter().map(|x| x.value).collect::>(), []); 1810 | { 1811 | let mut cur = l2.back_mut(); 1812 | l3 = cur.split_before(); 1813 | } 1814 | assert_eq!(l1.iter().map(|x| x.value).collect::>(), [1, 2]); 1815 | assert_eq!(l2.iter().map(|x| x.value).collect::>(), [4]); 1816 | assert_eq!(l3.iter().map(|x| x.value).collect::>(), [3]); 1817 | { 1818 | let mut cur = l1.front_mut(); 1819 | cur.splice_after(l2.take()); 1820 | } 1821 | assert_eq!(l1.iter().map(|x| x.value).collect::>(), [1, 4, 2]); 1822 | assert_eq!(l2.iter().map(|x| x.value).collect::>(), []); 1823 | assert_eq!(l3.iter().map(|x| x.value).collect::>(), [3]); 1824 | { 1825 | let mut cur = l1.front_mut(); 1826 | cur.move_next(); 1827 | cur.splice_before(l3.take()); 1828 | } 1829 | assert_eq!(l1.iter().map(|x| x.value).collect::>(), [1, 3, 4, 2]); 1830 | assert_eq!(l2.iter().map(|x| x.value).collect::>(), []); 1831 | assert_eq!(l3.iter().map(|x| x.value).collect::>(), []); 1832 | { 1833 | let mut cur = l2.cursor_mut(); 1834 | cur.splice_after(l1.take()); 1835 | } 1836 | assert_eq!(l1.iter().map(|x| x.value).collect::>(), []); 1837 | assert_eq!(l2.iter().map(|x| x.value).collect::>(), [1, 3, 4, 2]); 1838 | assert_eq!(l3.iter().map(|x| x.value).collect::>(), []); 1839 | { 1840 | let mut cur = l1.cursor_mut(); 1841 | cur.splice_before(l2.take()); 1842 | } 1843 | assert_eq!(l1.iter().map(|x| x.value).collect::>(), [1, 3, 4, 2]); 1844 | assert_eq!(l2.iter().map(|x| x.value).collect::>(), []); 1845 | assert_eq!(l3.iter().map(|x| x.value).collect::>(), []); 1846 | { 1847 | let mut cur = l1.cursor_mut(); 1848 | l2 = cur.split_after(); 1849 | } 1850 | assert_eq!(l1.iter().map(|x| x.value).collect::>(), []); 1851 | assert_eq!(l2.iter().map(|x| x.value).collect::>(), [1, 3, 4, 2]); 1852 | assert_eq!(l3.iter().map(|x| x.value).collect::>(), []); 1853 | { 1854 | let mut cur = l2.cursor_mut(); 1855 | l1 = cur.split_before(); 1856 | } 1857 | assert_eq!(l1.iter().map(|x| x.value).collect::>(), [1, 3, 4, 2]); 1858 | assert_eq!(l2.iter().map(|x| x.value).collect::>(), []); 1859 | assert_eq!(l3.iter().map(|x| x.value).collect::>(), []); 1860 | { 1861 | let mut cur = l1.front_mut(); 1862 | l2 = cur.split_before(); 1863 | } 1864 | assert_eq!(l1.iter().map(|x| x.value).collect::>(), [1, 3, 4, 2]); 1865 | assert_eq!(l2.iter().map(|x| x.value).collect::>(), []); 1866 | assert_eq!(l3.iter().map(|x| x.value).collect::>(), []); 1867 | { 1868 | let mut cur = l1.back_mut(); 1869 | l2 = cur.split_after(); 1870 | } 1871 | assert_eq!(l1.iter().map(|x| x.value).collect::>(), [1, 3, 4, 2]); 1872 | assert_eq!(l2.iter().map(|x| x.value).collect::>(), []); 1873 | assert_eq!(l3.iter().map(|x| x.value).collect::>(), []); 1874 | } 1875 | 1876 | #[test] 1877 | fn test_iter() { 1878 | let mut l = LinkedList::new(ObjAdapter1::new()); 1879 | let a = make_rc_obj(1); 1880 | let b = make_rc_obj(2); 1881 | let c = make_rc_obj(3); 1882 | let d = make_rc_obj(4); 1883 | l.cursor_mut().insert_before(a.clone()); 1884 | l.cursor_mut().insert_before(b.clone()); 1885 | l.cursor_mut().insert_before(c.clone()); 1886 | l.cursor_mut().insert_before(d.clone()); 1887 | 1888 | assert_eq!(l.front().get().unwrap().value, 1); 1889 | assert_eq!(l.back().get().unwrap().value, 4); 1890 | unsafe { 1891 | assert_eq!(l.cursor_from_ptr(b.as_ref()).get().unwrap().value, 2); 1892 | assert_eq!(l.cursor_mut_from_ptr(c.as_ref()).get().unwrap().value, 3); 1893 | } 1894 | 1895 | let mut v = Vec::new(); 1896 | for x in &l { 1897 | v.push(x.value); 1898 | } 1899 | assert_eq!(v, [1, 2, 3, 4]); 1900 | assert_eq!( 1901 | l.iter().clone().map(|x| x.value).collect::>(), 1902 | [1, 2, 3, 4] 1903 | ); 1904 | assert_eq!( 1905 | l.iter().rev().map(|x| x.value).collect::>(), 1906 | [4, 3, 2, 1] 1907 | ); 1908 | assert_eq!(l.iter().map(|x| x.value).collect::>(), [1, 2, 3, 4]); 1909 | 1910 | assert_eq!(format!("{:?}", l), "[1, 2, 3, 4]"); 1911 | 1912 | let mut v = Vec::new(); 1913 | for x in l.take() { 1914 | v.push(x.value); 1915 | } 1916 | assert_eq!(v, [1, 2, 3, 4]); 1917 | assert!(l.is_empty()); 1918 | assert!(!a.link1.is_linked()); 1919 | assert!(!b.link1.is_linked()); 1920 | assert!(!c.link1.is_linked()); 1921 | assert!(!d.link1.is_linked()); 1922 | 1923 | l.cursor_mut().insert_before(a.clone()); 1924 | l.cursor_mut().insert_before(b.clone()); 1925 | l.cursor_mut().insert_before(c.clone()); 1926 | l.cursor_mut().insert_before(d.clone()); 1927 | l.clear(); 1928 | assert!(l.is_empty()); 1929 | assert!(!a.link1.is_linked()); 1930 | assert!(!b.link1.is_linked()); 1931 | assert!(!c.link1.is_linked()); 1932 | assert!(!d.link1.is_linked()); 1933 | 1934 | v.clear(); 1935 | l.cursor_mut().insert_before(a.clone()); 1936 | l.cursor_mut().insert_before(b.clone()); 1937 | l.cursor_mut().insert_before(c.clone()); 1938 | l.cursor_mut().insert_before(d.clone()); 1939 | for x in l.into_iter().rev() { 1940 | v.push(x.value); 1941 | } 1942 | assert_eq!(v, [4, 3, 2, 1]); 1943 | assert!(!a.link1.is_linked()); 1944 | assert!(!b.link1.is_linked()); 1945 | assert!(!c.link1.is_linked()); 1946 | assert!(!d.link1.is_linked()); 1947 | } 1948 | 1949 | #[test] 1950 | fn test_multi_list() { 1951 | let mut l1 = LinkedList::new(ObjAdapter1::new()); 1952 | let mut l2 = LinkedList::new(ObjAdapter2::new()); 1953 | let a = make_rc_obj(1); 1954 | let b = make_rc_obj(2); 1955 | let c = make_rc_obj(3); 1956 | let d = make_rc_obj(4); 1957 | l1.cursor_mut().insert_before(a.clone()); 1958 | l1.cursor_mut().insert_before(b.clone()); 1959 | l1.cursor_mut().insert_before(c.clone()); 1960 | l1.cursor_mut().insert_before(d.clone()); 1961 | l2.cursor_mut().insert_after(a); 1962 | l2.cursor_mut().insert_after(b); 1963 | l2.cursor_mut().insert_after(c); 1964 | l2.cursor_mut().insert_after(d); 1965 | assert_eq!(l1.iter().map(|x| x.value).collect::>(), [1, 2, 3, 4]); 1966 | assert_eq!(l2.iter().map(|x| x.value).collect::>(), [4, 3, 2, 1]); 1967 | } 1968 | 1969 | #[test] 1970 | fn test_fast_clear_force_unlink() { 1971 | let mut l = LinkedList::new(UnsafeRefObjAdapter1::new()); 1972 | let a = UnsafeRef::from_box(Box::new(make_obj(1))); 1973 | let b = UnsafeRef::from_box(Box::new(make_obj(2))); 1974 | let c = UnsafeRef::from_box(Box::new(make_obj(3))); 1975 | l.cursor_mut().insert_before(a.clone()); 1976 | l.cursor_mut().insert_before(b.clone()); 1977 | l.cursor_mut().insert_before(c.clone()); 1978 | 1979 | l.fast_clear(); 1980 | assert!(l.is_empty()); 1981 | 1982 | unsafe { 1983 | assert!(a.link1.is_linked()); 1984 | assert!(b.link1.is_linked()); 1985 | assert!(c.link1.is_linked()); 1986 | 1987 | a.link1.force_unlink(); 1988 | b.link1.force_unlink(); 1989 | c.link1.force_unlink(); 1990 | 1991 | assert!(l.is_empty()); 1992 | 1993 | assert!(!a.link1.is_linked()); 1994 | assert!(!b.link1.is_linked()); 1995 | assert!(!c.link1.is_linked()); 1996 | } 1997 | 1998 | unsafe { 1999 | UnsafeRef::into_box(a); 2000 | UnsafeRef::into_box(b); 2001 | UnsafeRef::into_box(c); 2002 | } 2003 | } 2004 | 2005 | #[test] 2006 | fn test_non_static() { 2007 | #[derive(Clone)] 2008 | struct Obj<'a, T> { 2009 | link: Link, 2010 | value: &'a T, 2011 | } 2012 | intrusive_adapter!(ObjAdapter<'a, T> = &'a Obj<'a, T>: Obj<'a, T> {link: Link} where T: 'a); 2013 | 2014 | let v = 5; 2015 | let a = Obj { 2016 | link: Link::new(), 2017 | value: &v, 2018 | }; 2019 | let b = a.clone(); 2020 | let mut l = LinkedList::new(ObjAdapter::new()); 2021 | l.cursor_mut().insert_before(&a); 2022 | l.cursor_mut().insert_before(&b); 2023 | assert_eq!(*l.front().get().unwrap().value, 5); 2024 | assert_eq!(*l.back().get().unwrap().value, 5); 2025 | } 2026 | 2027 | macro_rules! test_clone_pointer { 2028 | ($ptr: ident, $ptr_import: path) => { 2029 | use $ptr_import; 2030 | 2031 | #[derive(Clone)] 2032 | struct Obj { 2033 | link: Link, 2034 | value: usize, 2035 | } 2036 | intrusive_adapter!(ObjAdapter = $ptr: Obj { link: Link }); 2037 | 2038 | let a = $ptr::new(Obj { 2039 | link: Link::new(), 2040 | value: 5, 2041 | }); 2042 | let mut l = LinkedList::new(ObjAdapter::new()); 2043 | l.cursor_mut().insert_before(a.clone()); 2044 | assert_eq!(2, $ptr::strong_count(&a)); 2045 | 2046 | let pointer = l.front().clone_pointer().unwrap(); 2047 | assert_eq!(pointer.value, 5); 2048 | assert_eq!(3, $ptr::strong_count(&a)); 2049 | 2050 | l.front_mut().remove(); 2051 | assert!(l.front().clone_pointer().is_none()); 2052 | }; 2053 | } 2054 | 2055 | #[test] 2056 | fn test_clone_pointer_rc() { 2057 | test_clone_pointer!(Rc, std::rc::Rc); 2058 | } 2059 | 2060 | #[test] 2061 | fn test_clone_pointer_arc() { 2062 | test_clone_pointer!(Arc, std::sync::Arc); 2063 | } 2064 | } 2065 | -------------------------------------------------------------------------------- /src/pointer_ops.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Amari Robinson 2 | // 3 | // Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be 6 | // copied, modified, or distributed except according to those terms. 7 | 8 | #[cfg(feature = "alloc")] 9 | use crate::alloc::boxed::Box; 10 | #[cfg(feature = "alloc")] 11 | use crate::alloc::rc::Rc; 12 | #[cfg(feature = "alloc")] 13 | use crate::alloc::sync::Arc; 14 | use crate::UnsafeRef; 15 | use core::marker::PhantomData; 16 | use core::mem::ManuallyDrop; 17 | use core::ops::Deref; 18 | use core::pin::Pin; 19 | 20 | /// Trait for pointer conversion operations. 21 | /// 22 | /// `Value` is the actual object type managed by the collection. This type will 23 | /// typically have a link as a struct field. 24 | /// 25 | /// `Pointer` is a pointer type which "owns" an object of type `Value`. 26 | /// Operations which insert an element into an intrusive collection will accept 27 | /// such a pointer and operations which remove an element will return this type. 28 | pub unsafe trait PointerOps { 29 | /// Object type which is inserted into an intrusive collection. 30 | type Value: ?Sized; 31 | /// Pointer type which owns an instance of a value. 32 | type Pointer; 33 | 34 | /// Constructs an owned pointer from a raw pointer. 35 | /// 36 | /// # Safety 37 | /// The raw pointer must have been previously returned by `into_raw`. 38 | /// 39 | /// An implementation of `from_raw` must not panic. 40 | unsafe fn from_raw(&self, value: *const Self::Value) -> Self::Pointer; 41 | 42 | /// Consumes the owned pointer and returns a raw pointer to the owned object. 43 | fn into_raw(&self, ptr: Self::Pointer) -> *const Self::Value; 44 | } 45 | 46 | /// The `PointerOps` type used by an `Adapter` generated by `intrusive_adapter!`. 47 | pub struct DefaultPointerOps(PhantomData); 48 | 49 | impl DefaultPointerOps { 50 | /// Constructs an instance of `DefaultPointerOps`. 51 | #[inline] 52 | pub const fn new() -> DefaultPointerOps { 53 | DefaultPointerOps(PhantomData) 54 | } 55 | } 56 | 57 | impl Clone for DefaultPointerOps { 58 | #[inline] 59 | fn clone(&self) -> Self { 60 | *self 61 | } 62 | } 63 | 64 | impl Copy for DefaultPointerOps {} 65 | 66 | impl Default for DefaultPointerOps { 67 | #[inline] 68 | fn default() -> Self { 69 | Self::new() 70 | } 71 | } 72 | 73 | unsafe impl<'a, T: ?Sized> PointerOps for DefaultPointerOps<&'a T> { 74 | type Value = T; 75 | type Pointer = &'a T; 76 | 77 | #[inline] 78 | unsafe fn from_raw(&self, raw: *const T) -> &'a T { 79 | &*raw 80 | } 81 | 82 | #[inline] 83 | fn into_raw(&self, ptr: &'a T) -> *const T { 84 | ptr 85 | } 86 | } 87 | 88 | unsafe impl<'a, T: ?Sized> PointerOps for DefaultPointerOps> { 89 | type Value = T; 90 | type Pointer = Pin<&'a T>; 91 | 92 | #[inline] 93 | unsafe fn from_raw(&self, raw: *const T) -> Pin<&'a T> { 94 | Pin::new_unchecked(&*raw) 95 | } 96 | 97 | #[inline] 98 | fn into_raw(&self, ptr: Pin<&'a T>) -> *const T { 99 | unsafe { Pin::into_inner_unchecked(ptr) as *const T } 100 | } 101 | } 102 | 103 | unsafe impl PointerOps for DefaultPointerOps> { 104 | type Value = T; 105 | type Pointer = UnsafeRef; 106 | 107 | #[inline] 108 | unsafe fn from_raw(&self, raw: *const T) -> UnsafeRef { 109 | UnsafeRef::from_raw(raw as *mut T) 110 | } 111 | 112 | #[inline] 113 | fn into_raw(&self, ptr: UnsafeRef) -> *const T { 114 | UnsafeRef::into_raw(ptr) as *const T 115 | } 116 | } 117 | 118 | unsafe impl PointerOps for DefaultPointerOps>> { 119 | type Value = T; 120 | type Pointer = Pin>; 121 | 122 | #[inline] 123 | unsafe fn from_raw(&self, raw: *const T) -> Pin> { 124 | Pin::new_unchecked(UnsafeRef::from_raw(raw as *mut T)) 125 | } 126 | 127 | #[inline] 128 | fn into_raw(&self, ptr: Pin>) -> *const T { 129 | UnsafeRef::into_raw(unsafe { Pin::into_inner_unchecked(ptr) }) as *const T 130 | } 131 | } 132 | 133 | #[cfg(feature = "alloc")] 134 | unsafe impl PointerOps for DefaultPointerOps> { 135 | type Value = T; 136 | type Pointer = Box; 137 | 138 | #[inline] 139 | unsafe fn from_raw(&self, raw: *const T) -> Box { 140 | Box::from_raw(raw as *mut T) 141 | } 142 | 143 | #[inline] 144 | fn into_raw(&self, ptr: Box) -> *const T { 145 | Box::into_raw(ptr) as *const T 146 | } 147 | } 148 | 149 | #[cfg(feature = "alloc")] 150 | unsafe impl PointerOps for DefaultPointerOps>> { 151 | type Value = T; 152 | type Pointer = Pin>; 153 | 154 | #[inline] 155 | unsafe fn from_raw(&self, raw: *const T) -> Pin> { 156 | Pin::new_unchecked(Box::from_raw(raw as *mut T)) 157 | } 158 | 159 | #[inline] 160 | fn into_raw(&self, ptr: Pin>) -> *const T { 161 | Box::into_raw(unsafe { Pin::into_inner_unchecked(ptr) }) as *const T 162 | } 163 | } 164 | 165 | #[cfg(feature = "alloc")] 166 | unsafe impl PointerOps for DefaultPointerOps> { 167 | type Value = T; 168 | type Pointer = Rc; 169 | 170 | #[inline] 171 | unsafe fn from_raw(&self, raw: *const T) -> Rc { 172 | Rc::from_raw(raw) 173 | } 174 | 175 | #[inline] 176 | fn into_raw(&self, ptr: Rc) -> *const T { 177 | Rc::into_raw(ptr) 178 | } 179 | } 180 | 181 | #[cfg(feature = "alloc")] 182 | unsafe impl PointerOps for DefaultPointerOps>> { 183 | type Value = T; 184 | type Pointer = Pin>; 185 | 186 | #[inline] 187 | unsafe fn from_raw(&self, raw: *const T) -> Pin> { 188 | Pin::new_unchecked(Rc::from_raw(raw)) 189 | } 190 | 191 | #[inline] 192 | fn into_raw(&self, ptr: Pin>) -> *const T { 193 | Rc::into_raw(unsafe { Pin::into_inner_unchecked(ptr) }) 194 | } 195 | } 196 | 197 | #[cfg(feature = "alloc")] 198 | unsafe impl PointerOps for DefaultPointerOps> { 199 | type Value = T; 200 | type Pointer = Arc; 201 | 202 | #[inline] 203 | unsafe fn from_raw(&self, raw: *const T) -> Arc { 204 | Arc::from_raw(raw) 205 | } 206 | 207 | #[inline] 208 | fn into_raw(&self, ptr: Arc) -> *const T { 209 | Arc::into_raw(ptr) 210 | } 211 | } 212 | 213 | #[cfg(feature = "alloc")] 214 | unsafe impl PointerOps for DefaultPointerOps>> { 215 | type Value = T; 216 | type Pointer = Pin>; 217 | 218 | #[inline] 219 | unsafe fn from_raw(&self, raw: *const T) -> Pin> { 220 | Pin::new_unchecked(Arc::from_raw(raw)) 221 | } 222 | 223 | #[inline] 224 | fn into_raw(&self, ptr: Pin>) -> *const T { 225 | Arc::into_raw(unsafe { Pin::into_inner_unchecked(ptr) }) 226 | } 227 | } 228 | 229 | /// Clones a `PointerOps::Pointer` from a `*const PointerOps::Value` 230 | /// 231 | /// This method is only safe to call if the raw pointer is known to be 232 | /// managed by the provided `PointerOps` type. 233 | #[inline] 234 | pub(crate) unsafe fn clone_pointer_from_raw( 235 | pointer_ops: &T, 236 | ptr: *const T::Value, 237 | ) -> T::Pointer 238 | where 239 | T::Pointer: Clone, 240 | { 241 | /// Guard which converts an pointer back into its raw version 242 | /// when it gets dropped. This makes sure we also perform a full 243 | /// `from_raw` and `into_raw` round trip - even in the case of panics. 244 | struct PointerGuard<'a, T: PointerOps> { 245 | pointer: ManuallyDrop, 246 | pointer_ops: &'a T, 247 | } 248 | 249 | impl<'a, T: PointerOps> Drop for PointerGuard<'a, T> { 250 | #[inline] 251 | fn drop(&mut self) { 252 | // Prevent shared pointers from being released by converting them 253 | // back into the raw pointers 254 | // SAFETY: `pointer` is never dropped. `ManuallyDrop::take` is not stable until 1.42.0. 255 | let _ = self 256 | .pointer_ops 257 | .into_raw(unsafe { core::ptr::read(&*self.pointer) }); 258 | } 259 | } 260 | 261 | let holder = PointerGuard { 262 | pointer: ManuallyDrop::new(pointer_ops.from_raw(ptr)), 263 | pointer_ops, 264 | }; 265 | holder.pointer.deref().clone() 266 | } 267 | 268 | #[cfg(test)] 269 | mod tests { 270 | use super::{DefaultPointerOps, PointerOps}; 271 | use std::boxed::Box; 272 | use std::fmt::Debug; 273 | use std::mem; 274 | use std::pin::Pin; 275 | use std::rc::Rc; 276 | use std::sync::Arc; 277 | 278 | #[test] 279 | fn test_box() { 280 | unsafe { 281 | let pointer_ops = DefaultPointerOps::>::new(); 282 | let p = Box::new(1); 283 | let a: *const i32 = &*p; 284 | let r = pointer_ops.into_raw(p); 285 | assert_eq!(a, r); 286 | let p2: Box = pointer_ops.from_raw(r); 287 | let a2: *const i32 = &*p2; 288 | assert_eq!(a, a2); 289 | } 290 | } 291 | 292 | #[test] 293 | fn test_rc() { 294 | unsafe { 295 | let pointer_ops = DefaultPointerOps::>::new(); 296 | let p = Rc::new(1); 297 | let a: *const i32 = &*p; 298 | let r = pointer_ops.into_raw(p); 299 | assert_eq!(a, r); 300 | let p2: Rc = pointer_ops.from_raw(r); 301 | let a2: *const i32 = &*p2; 302 | assert_eq!(a, a2); 303 | } 304 | } 305 | 306 | #[test] 307 | fn test_arc() { 308 | unsafe { 309 | let pointer_ops = DefaultPointerOps::>::new(); 310 | let p = Arc::new(1); 311 | let a: *const i32 = &*p; 312 | let r = pointer_ops.into_raw(p); 313 | assert_eq!(a, r); 314 | let p2: Arc = pointer_ops.from_raw(r); 315 | let a2: *const i32 = &*p2; 316 | assert_eq!(a, a2); 317 | } 318 | } 319 | 320 | #[test] 321 | fn test_box_unsized() { 322 | unsafe { 323 | let pointer_ops = DefaultPointerOps::>::new(); 324 | let p = Box::new(1) as Box; 325 | let a: *const dyn Debug = &*p; 326 | let b: (usize, usize) = mem::transmute(a); 327 | let r = pointer_ops.into_raw(p); 328 | assert_eq!(a, r); 329 | assert_eq!(b, mem::transmute(r)); 330 | let p2: Box = pointer_ops.from_raw(r); 331 | let a2: *const dyn Debug = &*p2; 332 | assert_eq!(a, a2); 333 | assert_eq!(b, mem::transmute(a2)); 334 | } 335 | } 336 | 337 | #[test] 338 | fn test_rc_unsized() { 339 | unsafe { 340 | let pointer_ops = DefaultPointerOps::>::new(); 341 | let p = Rc::new(1) as Rc; 342 | let a: *const dyn Debug = &*p; 343 | let b: (usize, usize) = mem::transmute(a); 344 | let r = pointer_ops.into_raw(p); 345 | assert_eq!(a, r); 346 | assert_eq!(b, mem::transmute(r)); 347 | let p2: Rc = pointer_ops.from_raw(r); 348 | let a2: *const dyn Debug = &*p2; 349 | assert_eq!(a, a2); 350 | assert_eq!(b, mem::transmute(a2)); 351 | } 352 | } 353 | 354 | #[test] 355 | fn test_arc_unsized() { 356 | unsafe { 357 | let pointer_ops = DefaultPointerOps::>::new(); 358 | let p = Arc::new(1) as Arc; 359 | let a: *const dyn Debug = &*p; 360 | let b: (usize, usize) = mem::transmute(a); 361 | let r = pointer_ops.into_raw(p); 362 | assert_eq!(a, r); 363 | assert_eq!(b, mem::transmute(r)); 364 | let p2: Arc = pointer_ops.from_raw(r); 365 | let a2: *const dyn Debug = &*p2; 366 | assert_eq!(a, a2); 367 | assert_eq!(b, mem::transmute(a2)); 368 | } 369 | } 370 | 371 | #[test] 372 | fn clone_arc_from_raw() { 373 | use super::clone_pointer_from_raw; 374 | unsafe { 375 | let pointer_ops = DefaultPointerOps::>::new(); 376 | let p = Arc::new(1); 377 | let raw = Arc::as_ptr(&p); 378 | let p2: Arc = clone_pointer_from_raw(&pointer_ops, raw); 379 | assert_eq!(2, Arc::strong_count(&p2)); 380 | } 381 | } 382 | 383 | #[test] 384 | fn clone_rc_from_raw() { 385 | use super::clone_pointer_from_raw; 386 | unsafe { 387 | let pointer_ops = DefaultPointerOps::>::new(); 388 | let p = Rc::new(1); 389 | let raw = Rc::as_ptr(&p); 390 | let p2: Rc = clone_pointer_from_raw(&pointer_ops, raw); 391 | assert_eq!(2, Rc::strong_count(&p2)); 392 | } 393 | } 394 | 395 | #[test] 396 | fn test_pin_box() { 397 | unsafe { 398 | let pointer_ops = DefaultPointerOps::>>::new(); 399 | let p = Pin::new(Box::new(1)); 400 | let a: *const i32 = &*p; 401 | let r = pointer_ops.into_raw(p); 402 | assert_eq!(a, r); 403 | let p2: Pin> = pointer_ops.from_raw(r); 404 | let a2: *const i32 = &*p2; 405 | assert_eq!(a, a2); 406 | } 407 | } 408 | 409 | #[test] 410 | fn test_pin_rc() { 411 | unsafe { 412 | let pointer_ops = DefaultPointerOps::>>::new(); 413 | let p = Pin::new(Rc::new(1)); 414 | let a: *const i32 = &*p; 415 | let r = pointer_ops.into_raw(p); 416 | assert_eq!(a, r); 417 | let p2: Pin> = pointer_ops.from_raw(r); 418 | let a2: *const i32 = &*p2; 419 | assert_eq!(a, a2); 420 | } 421 | } 422 | 423 | #[test] 424 | fn test_pin_arc() { 425 | unsafe { 426 | let pointer_ops = DefaultPointerOps::>>::new(); 427 | let p = Pin::new(Arc::new(1)); 428 | let a: *const i32 = &*p; 429 | let r = pointer_ops.into_raw(p); 430 | assert_eq!(a, r); 431 | let p2: Pin> = pointer_ops.from_raw(r); 432 | let a2: *const i32 = &*p2; 433 | assert_eq!(a, a2); 434 | } 435 | } 436 | 437 | #[test] 438 | fn test_pin_box_unsized() { 439 | unsafe { 440 | let pointer_ops = DefaultPointerOps::>>::new(); 441 | let p = Pin::new(Box::new(1)) as Pin>; 442 | let a: *const dyn Debug = &*p; 443 | let b: (usize, usize) = mem::transmute(a); 444 | let r = pointer_ops.into_raw(p); 445 | assert_eq!(a, r); 446 | assert_eq!(b, mem::transmute(r)); 447 | let p2: Pin> = pointer_ops.from_raw(r); 448 | let a2: *const dyn Debug = &*p2; 449 | assert_eq!(a, a2); 450 | assert_eq!(b, mem::transmute(a2)); 451 | } 452 | } 453 | 454 | #[test] 455 | fn test_pin_rc_unsized() { 456 | unsafe { 457 | let pointer_ops = DefaultPointerOps::>>::new(); 458 | let p = Pin::new(Rc::new(1)) as Pin>; 459 | let a: *const dyn Debug = &*p; 460 | let b: (usize, usize) = mem::transmute(a); 461 | let r = pointer_ops.into_raw(p); 462 | assert_eq!(a, r); 463 | assert_eq!(b, mem::transmute(r)); 464 | let p2: Pin> = pointer_ops.from_raw(r); 465 | let a2: *const dyn Debug = &*p2; 466 | assert_eq!(a, a2); 467 | assert_eq!(b, mem::transmute(a2)); 468 | } 469 | } 470 | 471 | #[test] 472 | fn test_pin_arc_unsized() { 473 | unsafe { 474 | let pointer_ops = DefaultPointerOps::>>::new(); 475 | let p = Pin::new(Arc::new(1)) as Pin>; 476 | let a: *const dyn Debug = &*p; 477 | let b: (usize, usize) = mem::transmute(a); 478 | let r = pointer_ops.into_raw(p); 479 | assert_eq!(a, r); 480 | assert_eq!(b, mem::transmute(r)); 481 | let p2: Pin> = pointer_ops.from_raw(r); 482 | let a2: *const dyn Debug = &*p2; 483 | assert_eq!(a, a2); 484 | assert_eq!(b, mem::transmute(a2)); 485 | } 486 | } 487 | 488 | #[test] 489 | fn clone_pin_arc_from_raw() { 490 | use super::clone_pointer_from_raw; 491 | unsafe { 492 | let pointer_ops = DefaultPointerOps::>>::new(); 493 | let p = Pin::new(Arc::new(1)); 494 | let raw = pointer_ops.into_raw(p); 495 | let p2: Pin> = clone_pointer_from_raw(&pointer_ops, raw); 496 | let _p = pointer_ops.from_raw(raw); 497 | assert_eq!(2, Arc::strong_count(&Pin::into_inner(p2))); 498 | } 499 | } 500 | 501 | #[test] 502 | fn clone_pin_rc_from_raw() { 503 | use super::clone_pointer_from_raw; 504 | unsafe { 505 | let pointer_ops = DefaultPointerOps::>>::new(); 506 | let p = Pin::new(Rc::new(1)); 507 | let raw = pointer_ops.into_raw(p); 508 | let p2: Pin> = clone_pointer_from_raw(&pointer_ops, raw); 509 | let _p = pointer_ops.from_raw(raw); 510 | assert_eq!(2, Rc::strong_count(&Pin::into_inner(p2))); 511 | } 512 | } 513 | } 514 | -------------------------------------------------------------------------------- /src/singly_linked_list.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Amanieu d'Antras 2 | // Copyright 2020 Amari Robinson 3 | // 4 | // Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be 7 | // copied, modified, or distributed except according to those terms. 8 | 9 | //! Intrusive singly-linked list. 10 | 11 | use core::cell::Cell; 12 | use core::fmt; 13 | use core::ptr::{null_mut, NonNull}; 14 | use core::sync::atomic::{AtomicPtr, Ordering}; 15 | 16 | use crate::link_ops::{self, DefaultLinkOps}; 17 | use crate::pointer_ops::PointerOps; 18 | use crate::xor_linked_list::XorLinkedListOps; 19 | use crate::Adapter; 20 | 21 | // ============================================================================= 22 | // SinglyLinkedListOps 23 | // ============================================================================= 24 | 25 | /// Link operations for `SinglyLinkedList`. 26 | pub unsafe trait SinglyLinkedListOps: link_ops::LinkOps { 27 | /// Returns the "next" link pointer of `ptr`. 28 | /// 29 | /// # Safety 30 | /// An implementation of `next` must not panic. 31 | unsafe fn next(&self, ptr: Self::LinkPtr) -> Option; 32 | 33 | /// Sets the "next" link pointer of `ptr`. 34 | /// 35 | /// # Safety 36 | /// An implementation of `set_next` must not panic. 37 | unsafe fn set_next(&mut self, ptr: Self::LinkPtr, next: Option); 38 | } 39 | 40 | // ============================================================================= 41 | // Link 42 | // ============================================================================= 43 | 44 | /// Intrusive link that allows an object to be inserted into a 45 | /// `SinglyLinkedList`. 46 | #[repr(align(2))] 47 | pub struct Link { 48 | next: Cell>>, 49 | } 50 | 51 | // Use a special value to indicate an unlinked node 52 | const UNLINKED_MARKER: Option> = 53 | unsafe { Some(NonNull::new_unchecked(1 as *mut Link)) }; 54 | 55 | impl Link { 56 | /// Creates a new `Link`. 57 | #[inline] 58 | pub const fn new() -> Link { 59 | Link { 60 | next: Cell::new(UNLINKED_MARKER), 61 | } 62 | } 63 | 64 | /// Checks whether the `Link` is linked into a `SinglyLinkedList`. 65 | #[inline] 66 | pub fn is_linked(&self) -> bool { 67 | self.next.get() != UNLINKED_MARKER 68 | } 69 | 70 | /// Forcibly unlinks an object from a `SinglyLinkedList`. 71 | /// 72 | /// # Safety 73 | /// 74 | /// It is undefined behavior to call this function while still linked into a 75 | /// `SinglyLinkedList`. The only situation where this function is useful is 76 | /// after calling `fast_clear` on a `SinglyLinkedList`, since this clears 77 | /// the collection without marking the nodes as unlinked. 78 | #[inline] 79 | pub unsafe fn force_unlink(&self) { 80 | self.next.set(UNLINKED_MARKER); 81 | } 82 | } 83 | 84 | impl DefaultLinkOps for Link { 85 | type Ops = LinkOps; 86 | 87 | const NEW: Self::Ops = LinkOps; 88 | } 89 | 90 | // An object containing a link can be sent to another thread if it is unlinked. 91 | unsafe impl Send for Link {} 92 | 93 | // Provide an implementation of Clone which simply initializes the new link as 94 | // unlinked. This allows structs containing a link to derive Clone. 95 | impl Clone for Link { 96 | #[inline] 97 | fn clone(&self) -> Link { 98 | Link::new() 99 | } 100 | } 101 | 102 | // Same as above 103 | impl Default for Link { 104 | #[inline] 105 | fn default() -> Link { 106 | Link::new() 107 | } 108 | } 109 | 110 | // Provide an implementation of Debug so that structs containing a link can 111 | // still derive Debug. 112 | impl fmt::Debug for Link { 113 | #[inline] 114 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 115 | // There isn't anything sensible to print here except whether the link 116 | // is currently in a list. 117 | if self.is_linked() { 118 | write!(f, "linked") 119 | } else { 120 | write!(f, "unlinked") 121 | } 122 | } 123 | } 124 | 125 | // ============================================================================= 126 | // LinkOps 127 | // ============================================================================= 128 | 129 | /// Default `LinkOps` implementation for `SinglyLinkedList`. 130 | #[derive(Clone, Copy, Default)] 131 | pub struct LinkOps; 132 | 133 | unsafe impl link_ops::LinkOps for LinkOps { 134 | type LinkPtr = NonNull; 135 | 136 | #[inline] 137 | unsafe fn acquire_link(&mut self, ptr: Self::LinkPtr) -> bool { 138 | if ptr.as_ref().is_linked() { 139 | false 140 | } else { 141 | ptr.as_ref().next.set(None); 142 | true 143 | } 144 | } 145 | 146 | #[inline] 147 | unsafe fn release_link(&mut self, ptr: Self::LinkPtr) { 148 | ptr.as_ref().next.set(UNLINKED_MARKER); 149 | } 150 | } 151 | 152 | unsafe impl SinglyLinkedListOps for LinkOps { 153 | #[inline] 154 | unsafe fn next(&self, ptr: Self::LinkPtr) -> Option { 155 | ptr.as_ref().next.get() 156 | } 157 | 158 | #[inline] 159 | unsafe fn set_next(&mut self, ptr: Self::LinkPtr, next: Option) { 160 | ptr.as_ref().next.set(next); 161 | } 162 | } 163 | 164 | unsafe impl XorLinkedListOps for LinkOps { 165 | #[inline] 166 | unsafe fn next( 167 | &self, 168 | ptr: Self::LinkPtr, 169 | prev: Option, 170 | ) -> Option { 171 | let packed = ptr 172 | .as_ref() 173 | .next 174 | .get() 175 | .map(|x| x.as_ptr() as usize) 176 | .unwrap_or(0); 177 | let raw = packed ^ prev.map(|x| x.as_ptr() as usize).unwrap_or(0); 178 | 179 | NonNull::new(raw as *mut _) 180 | } 181 | 182 | #[inline] 183 | unsafe fn prev( 184 | &self, 185 | ptr: Self::LinkPtr, 186 | next: Option, 187 | ) -> Option { 188 | let packed = ptr 189 | .as_ref() 190 | .next 191 | .get() 192 | .map(|x| x.as_ptr() as usize) 193 | .unwrap_or(0); 194 | let raw = packed ^ next.map(|x| x.as_ptr() as usize).unwrap_or(0); 195 | NonNull::new(raw as *mut _) 196 | } 197 | 198 | #[inline] 199 | unsafe fn set( 200 | &mut self, 201 | ptr: Self::LinkPtr, 202 | prev: Option, 203 | next: Option, 204 | ) { 205 | let new_packed = prev.map(|x| x.as_ptr() as usize).unwrap_or(0) 206 | ^ next.map(|x| x.as_ptr() as usize).unwrap_or(0); 207 | 208 | let new_next = NonNull::new(new_packed as *mut _); 209 | ptr.as_ref().next.set(new_next); 210 | } 211 | 212 | #[inline] 213 | unsafe fn replace_next_or_prev( 214 | &mut self, 215 | ptr: Self::LinkPtr, 216 | old: Option, 217 | new: Option, 218 | ) { 219 | let packed = ptr 220 | .as_ref() 221 | .next 222 | .get() 223 | .map(|x| x.as_ptr() as usize) 224 | .unwrap_or(0); 225 | let new_packed = packed 226 | ^ old.map(|x| x.as_ptr() as usize).unwrap_or(0) 227 | ^ new.map(|x| x.as_ptr() as usize).unwrap_or(0); 228 | 229 | let new_next = NonNull::new(new_packed as *mut _); 230 | ptr.as_ref().next.set(new_next); 231 | } 232 | } 233 | 234 | // ============================================================================= 235 | // AtomicLink 236 | // ============================================================================= 237 | 238 | /// Intrusive link that allows an object to be inserted into a 239 | /// `SinglyLinkedList`. This link allows the structure to be shared between threads. 240 | #[repr(align(2))] 241 | pub struct AtomicLink { 242 | next: AtomicPtr, 243 | } 244 | const ATOMIC_UNLINKED_MARKER: *mut AtomicLink = 1 as *mut AtomicLink; 245 | 246 | impl AtomicLink { 247 | /// Creates a new `AtomicLink`. 248 | #[inline] 249 | pub const fn new() -> AtomicLink { 250 | AtomicLink { 251 | next: AtomicPtr::new(ATOMIC_UNLINKED_MARKER), 252 | } 253 | } 254 | 255 | /// Checks whether the `AtomicLink` is linked into a `SinglyLinkedList`. 256 | #[inline] 257 | pub fn is_linked(&self) -> bool { 258 | self.next.load(Ordering::Relaxed) != ATOMIC_UNLINKED_MARKER 259 | } 260 | 261 | /// Forcibly unlinks an object from a `SinglyLinkedList`. 262 | /// 263 | /// # Safety 264 | /// 265 | /// It is undefined behavior to call this function while still linked into a 266 | /// `SinglyLinkedList`. The only situation where this function is useful is 267 | /// after calling `fast_clear` on a `SinglyLinkedList`, since this clears 268 | /// the collection without marking the nodes as unlinked. 269 | #[inline] 270 | pub unsafe fn force_unlink(&self) { 271 | self.next.store(ATOMIC_UNLINKED_MARKER, Ordering::Release); 272 | } 273 | 274 | /// Access the `next` pointer in an exclusive context. 275 | /// 276 | /// # Safety 277 | /// 278 | /// This can only be called after `acquire_link` has been succesfully called. 279 | #[inline] 280 | unsafe fn next_exclusive(&self) -> &Cell>> { 281 | // This is safe because currently AtomicPtr has the same representation Cell>>. 282 | core::mem::transmute(&self.next) 283 | } 284 | } 285 | 286 | impl DefaultLinkOps for AtomicLink { 287 | type Ops = AtomicLinkOps; 288 | 289 | const NEW: Self::Ops = AtomicLinkOps; 290 | } 291 | 292 | // An object containing a link can be sent to another thread since `acquire_link` is atomic. 293 | unsafe impl Send for AtomicLink {} 294 | 295 | // An object containing a link can be shared between threads since `acquire_link` is atomic. 296 | unsafe impl Sync for AtomicLink {} 297 | 298 | impl Clone for AtomicLink { 299 | #[inline] 300 | fn clone(&self) -> AtomicLink { 301 | AtomicLink::new() 302 | } 303 | } 304 | 305 | impl Default for AtomicLink { 306 | #[inline] 307 | fn default() -> AtomicLink { 308 | AtomicLink::new() 309 | } 310 | } 311 | 312 | // Provide an implementation of Debug so that structs containing a link can 313 | // still derive Debug. 314 | impl fmt::Debug for AtomicLink { 315 | #[inline] 316 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 317 | // There isn't anything sensible to print here except whether the link 318 | // is currently in a list. 319 | if self.is_linked() { 320 | write!(f, "linked") 321 | } else { 322 | write!(f, "unlinked") 323 | } 324 | } 325 | } 326 | 327 | // ============================================================================= 328 | // AtomicLinkOps 329 | // ============================================================================= 330 | 331 | /// Default `AtomicLinkOps` implementation for `LinkedList`. 332 | #[derive(Clone, Copy, Default)] 333 | pub struct AtomicLinkOps; 334 | 335 | unsafe impl link_ops::LinkOps for AtomicLinkOps { 336 | type LinkPtr = NonNull; 337 | 338 | #[inline] 339 | unsafe fn acquire_link(&mut self, ptr: Self::LinkPtr) -> bool { 340 | ptr.as_ref() 341 | .next 342 | .compare_exchange( 343 | ATOMIC_UNLINKED_MARKER, 344 | null_mut(), 345 | Ordering::Acquire, 346 | Ordering::Relaxed, 347 | ) 348 | .is_ok() 349 | } 350 | 351 | #[inline] 352 | unsafe fn release_link(&mut self, ptr: Self::LinkPtr) { 353 | ptr.as_ref() 354 | .next 355 | .store(ATOMIC_UNLINKED_MARKER, Ordering::Release) 356 | } 357 | } 358 | 359 | unsafe impl SinglyLinkedListOps for AtomicLinkOps { 360 | #[inline] 361 | unsafe fn next(&self, ptr: Self::LinkPtr) -> Option { 362 | ptr.as_ref().next_exclusive().get() 363 | } 364 | 365 | #[inline] 366 | unsafe fn set_next(&mut self, ptr: Self::LinkPtr, next: Option) { 367 | ptr.as_ref().next_exclusive().set(next); 368 | } 369 | } 370 | 371 | unsafe impl XorLinkedListOps for AtomicLinkOps { 372 | #[inline] 373 | unsafe fn next( 374 | &self, 375 | ptr: Self::LinkPtr, 376 | prev: Option, 377 | ) -> Option { 378 | let packed = ptr 379 | .as_ref() 380 | .next_exclusive() 381 | .get() 382 | .map(|x| x.as_ptr() as usize) 383 | .unwrap_or(0); 384 | let raw = packed ^ prev.map(|x| x.as_ptr() as usize).unwrap_or(0); 385 | 386 | NonNull::new(raw as *mut _) 387 | } 388 | 389 | #[inline] 390 | unsafe fn prev( 391 | &self, 392 | ptr: Self::LinkPtr, 393 | next: Option, 394 | ) -> Option { 395 | let packed = ptr 396 | .as_ref() 397 | .next_exclusive() 398 | .get() 399 | .map(|x| x.as_ptr() as usize) 400 | .unwrap_or(0); 401 | let raw = packed ^ next.map(|x| x.as_ptr() as usize).unwrap_or(0); 402 | NonNull::new(raw as *mut _) 403 | } 404 | 405 | #[inline] 406 | unsafe fn set( 407 | &mut self, 408 | ptr: Self::LinkPtr, 409 | prev: Option, 410 | next: Option, 411 | ) { 412 | let new_packed = prev.map(|x| x.as_ptr() as usize).unwrap_or(0) 413 | ^ next.map(|x| x.as_ptr() as usize).unwrap_or(0); 414 | 415 | let new_next = NonNull::new(new_packed as *mut _); 416 | ptr.as_ref().next_exclusive().set(new_next); 417 | } 418 | 419 | #[inline] 420 | unsafe fn replace_next_or_prev( 421 | &mut self, 422 | ptr: Self::LinkPtr, 423 | old: Option, 424 | new: Option, 425 | ) { 426 | let packed = ptr 427 | .as_ref() 428 | .next_exclusive() 429 | .get() 430 | .map(|x| x.as_ptr() as usize) 431 | .unwrap_or(0); 432 | let new_packed = packed 433 | ^ old.map(|x| x.as_ptr() as usize).unwrap_or(0) 434 | ^ new.map(|x| x.as_ptr() as usize).unwrap_or(0); 435 | 436 | let new_next = NonNull::new(new_packed as *mut _); 437 | ptr.as_ref().next_exclusive().set(new_next); 438 | } 439 | } 440 | 441 | #[inline] 442 | unsafe fn link_between( 443 | link_ops: &mut T, 444 | ptr: T::LinkPtr, 445 | prev: Option, 446 | next: Option, 447 | ) { 448 | if let Some(prev) = prev { 449 | link_ops.set_next(prev, Some(ptr)); 450 | } 451 | link_ops.set_next(ptr, next); 452 | } 453 | 454 | #[inline] 455 | unsafe fn link_after(link_ops: &mut T, ptr: T::LinkPtr, prev: T::LinkPtr) { 456 | link_between(link_ops, ptr, Some(prev), link_ops.next(prev)); 457 | } 458 | 459 | #[inline] 460 | unsafe fn replace_with( 461 | link_ops: &mut T, 462 | ptr: T::LinkPtr, 463 | prev: Option, 464 | new: T::LinkPtr, 465 | ) { 466 | if let Some(prev) = prev { 467 | link_ops.set_next(prev, Some(new)); 468 | } 469 | link_ops.set_next(new, link_ops.next(ptr)); 470 | link_ops.release_link(ptr); 471 | } 472 | 473 | #[inline] 474 | unsafe fn remove( 475 | link_ops: &mut T, 476 | ptr: T::LinkPtr, 477 | prev: Option, 478 | ) { 479 | if let Some(prev) = prev { 480 | link_ops.set_next(prev, link_ops.next(ptr)); 481 | } 482 | link_ops.release_link(ptr); 483 | } 484 | 485 | #[inline] 486 | unsafe fn splice( 487 | link_ops: &mut T, 488 | start: T::LinkPtr, 489 | end: T::LinkPtr, 490 | prev: Option, 491 | next: Option, 492 | ) { 493 | link_ops.set_next(end, next); 494 | if let Some(prev) = prev { 495 | link_ops.set_next(prev, Some(start)); 496 | } 497 | } 498 | 499 | // ============================================================================= 500 | // Cursor, CursorMut, CursorOwning 501 | // ============================================================================= 502 | 503 | /// A cursor which provides read-only access to a `SinglyLinkedList`. 504 | pub struct Cursor<'a, A: Adapter> 505 | where 506 | A::LinkOps: SinglyLinkedListOps, 507 | { 508 | current: Option<::LinkPtr>, 509 | list: &'a SinglyLinkedList, 510 | } 511 | 512 | impl<'a, A: Adapter> Clone for Cursor<'a, A> 513 | where 514 | A::LinkOps: SinglyLinkedListOps, 515 | { 516 | #[inline] 517 | fn clone(&self) -> Cursor<'a, A> { 518 | Cursor { 519 | current: self.current, 520 | list: self.list, 521 | } 522 | } 523 | } 524 | 525 | impl<'a, A: Adapter> Cursor<'a, A> 526 | where 527 | A::LinkOps: SinglyLinkedListOps, 528 | { 529 | /// Checks if the cursor is currently pointing to the null object. 530 | #[inline] 531 | pub fn is_null(&self) -> bool { 532 | self.current.is_none() 533 | } 534 | 535 | /// Returns a reference to the object that the cursor is currently 536 | /// pointing to. 537 | /// 538 | /// This returns `None` if the cursor is currently pointing to the null 539 | /// object. 540 | #[inline] 541 | pub fn get(&self) -> Option<&'a ::Value> { 542 | Some(unsafe { &*self.list.adapter.get_value(self.current?) }) 543 | } 544 | 545 | /// Clones and returns the pointer that points to the element that the 546 | /// cursor is referencing. 547 | /// 548 | /// This returns `None` if the cursor is currently pointing to the null 549 | /// object. 550 | #[inline] 551 | pub fn clone_pointer(&self) -> Option<::Pointer> 552 | where 553 | ::Pointer: Clone, 554 | { 555 | let raw_pointer = unsafe { self.list.adapter.get_value(self.current?) }; 556 | Some(unsafe { 557 | crate::pointer_ops::clone_pointer_from_raw(self.list.adapter.pointer_ops(), raw_pointer) 558 | }) 559 | } 560 | 561 | /// Moves the cursor to the next element of the `SinglyLinkedList`. 562 | /// 563 | /// If the cursor is pointer to the null object then this will move it to 564 | /// the first element of the `SinglyLinkedList`. If it is pointing to the 565 | /// last element of the `SinglyLinkedList` then this will move it to the 566 | /// null object. 567 | #[inline] 568 | pub fn move_next(&mut self) { 569 | if let Some(current) = self.current { 570 | self.current = unsafe { self.list.adapter.link_ops().next(current) }; 571 | } else { 572 | self.current = self.list.head; 573 | } 574 | } 575 | 576 | /// Returns a cursor pointing to the next element of the `SinglyLinkedList`. 577 | /// 578 | /// If the cursor is pointer to the null object then this will return the 579 | /// first element of the `SinglyLinkedList`. If it is pointing to the last 580 | /// element of the `SinglyLinkedList` then this will return a null cursor. 581 | #[inline] 582 | pub fn peek_next(&self) -> Cursor<'_, A> { 583 | let mut next = self.clone(); 584 | next.move_next(); 585 | next 586 | } 587 | } 588 | 589 | /// A cursor which provides mutable access to a `SinglyLinkedList`. 590 | pub struct CursorMut<'a, A: Adapter> 591 | where 592 | A::LinkOps: SinglyLinkedListOps, 593 | { 594 | current: Option<::LinkPtr>, 595 | list: &'a mut SinglyLinkedList, 596 | } 597 | 598 | impl<'a, A: Adapter> CursorMut<'a, A> 599 | where 600 | A::LinkOps: SinglyLinkedListOps, 601 | { 602 | /// Checks if the cursor is currently pointing to the null object. 603 | #[inline] 604 | pub fn is_null(&self) -> bool { 605 | self.current.is_none() 606 | } 607 | 608 | /// Returns a reference to the object that the cursor is currently 609 | /// pointing to. 610 | /// 611 | /// This returns None if the cursor is currently pointing to the null 612 | /// object. 613 | #[inline] 614 | pub fn get(&self) -> Option<&::Value> { 615 | Some(unsafe { &*self.list.adapter.get_value(self.current?) }) 616 | } 617 | 618 | /// Returns a read-only cursor pointing to the current element. 619 | /// 620 | /// The lifetime of the returned `Cursor` is bound to that of the 621 | /// `CursorMut`, which means it cannot outlive the `CursorMut` and that the 622 | /// `CursorMut` is frozen for the lifetime of the `Cursor`. 623 | #[inline] 624 | pub fn as_cursor(&self) -> Cursor<'_, A> { 625 | Cursor { 626 | current: self.current, 627 | list: self.list, 628 | } 629 | } 630 | 631 | /// Moves the cursor to the next element of the `SinglyLinkedList`. 632 | /// 633 | /// If the cursor is pointer to the null object then this will move it to 634 | /// the first element of the `SinglyLinkedList`. If it is pointing to the 635 | /// last element of the `SinglyLinkedList` then this will move it to the 636 | /// null object. 637 | #[inline] 638 | pub fn move_next(&mut self) { 639 | if let Some(current) = self.current { 640 | self.current = unsafe { self.list.adapter.link_ops().next(current) }; 641 | } else { 642 | self.current = self.list.head; 643 | } 644 | } 645 | 646 | /// Returns a cursor pointing to the next element of the `SinglyLinkedList`. 647 | /// 648 | /// If the cursor is pointer to the null object then this will return the 649 | /// first element of the `SinglyLinkedList`. If it is pointing to the last 650 | /// element of the `SinglyLinkedList` then this will return a null cursor. 651 | #[inline] 652 | pub fn peek_next(&self) -> Cursor<'_, A> { 653 | let mut next = self.as_cursor(); 654 | next.move_next(); 655 | next 656 | } 657 | 658 | /// Removes the next element from the `SinglyLinkedList`. 659 | /// 660 | /// A pointer to the element that was removed is returned, and the cursor is 661 | /// not moved. 662 | /// 663 | /// If the cursor is currently pointing to the last element of the 664 | /// `SinglyLinkedList` then no element is removed and `None` is returned. 665 | #[inline] 666 | pub fn remove_next(&mut self) -> Option<::Pointer> { 667 | unsafe { 668 | let next = if let Some(current) = self.current { 669 | self.list.adapter.link_ops().next(current) 670 | } else { 671 | self.list.head 672 | }?; 673 | 674 | if self.is_null() { 675 | self.list.head = self.list.adapter.link_ops().next(next); 676 | } 677 | remove(self.list.adapter.link_ops_mut(), next, self.current); 678 | 679 | Some( 680 | self.list 681 | .adapter 682 | .pointer_ops() 683 | .from_raw(self.list.adapter.get_value(next)), 684 | ) 685 | } 686 | } 687 | 688 | /// Removes the next element from the `SinglyLinkedList` and inserts 689 | /// another object in its place. 690 | /// 691 | /// A pointer to the element that was removed is returned, and the cursor is 692 | /// not moved. 693 | /// 694 | /// If the cursor is currently pointing to the last element of the 695 | /// `SinglyLinkedList` then no element is added or removed and an error is 696 | /// returned containing the given `val` parameter. 697 | /// 698 | /// # Panics 699 | /// 700 | /// Panics if the new element is already linked to a different intrusive 701 | /// collection. 702 | #[inline] 703 | pub fn replace_next_with( 704 | &mut self, 705 | val: ::Pointer, 706 | ) -> Result<::Pointer, ::Pointer> 707 | { 708 | unsafe { 709 | let next = if let Some(current) = self.current { 710 | self.list.adapter.link_ops().next(current) 711 | } else { 712 | self.list.head 713 | }; 714 | match next { 715 | Some(next) => { 716 | let new = self.list.node_from_value(val); 717 | if self.is_null() { 718 | self.list.head = Some(new); 719 | } 720 | replace_with(self.list.adapter.link_ops_mut(), next, self.current, new); 721 | Ok(self 722 | .list 723 | .adapter 724 | .pointer_ops() 725 | .from_raw(self.list.adapter.get_value(next))) 726 | } 727 | None => Err(val), 728 | } 729 | } 730 | } 731 | 732 | /// Inserts a new element into the `SinglyLinkedList` after the current one. 733 | /// 734 | /// If the cursor is pointing at the null object then the new element is 735 | /// inserted at the front of the `SinglyLinkedList`. 736 | /// 737 | /// # Panics 738 | /// 739 | /// Panics if the new element is already linked to a different intrusive 740 | /// collection. 741 | #[inline] 742 | pub fn insert_after(&mut self, val: ::Pointer) { 743 | unsafe { 744 | let new = self.list.node_from_value(val); 745 | if let Some(current) = self.current { 746 | link_after(self.list.adapter.link_ops_mut(), new, current); 747 | } else { 748 | link_between(self.list.adapter.link_ops_mut(), new, None, self.list.head); 749 | self.list.head = Some(new); 750 | } 751 | } 752 | } 753 | 754 | /// Inserts the elements from the given `SinglyLinkedList` after the current 755 | /// one. 756 | /// 757 | /// If the cursor is pointing at the null object then the new elements are 758 | /// inserted at the start of the `SinglyLinkedList`. 759 | /// 760 | /// Note that if the cursor is not pointing to the last element of the 761 | /// `SinglyLinkedList` then the given list must be scanned to find its last 762 | /// element. This has linear time complexity. 763 | #[inline] 764 | pub fn splice_after(&mut self, mut list: SinglyLinkedList) { 765 | if let Some(head) = list.head { 766 | unsafe { 767 | let next = if let Some(current) = self.current { 768 | self.list.adapter.link_ops().next(current) 769 | } else { 770 | self.list.head 771 | }; 772 | if let Some(next) = next { 773 | let mut tail = head; 774 | while let Some(x) = self.list.adapter.link_ops().next(tail) { 775 | tail = x; 776 | } 777 | splice( 778 | self.list.adapter.link_ops_mut(), 779 | head, 780 | tail, 781 | self.current, 782 | Some(next), 783 | ); 784 | if self.is_null() { 785 | self.list.head = list.head; 786 | } 787 | } else { 788 | if let Some(current) = self.current { 789 | self.list 790 | .adapter 791 | .link_ops_mut() 792 | .set_next(current, list.head); 793 | } else { 794 | self.list.head = list.head; 795 | } 796 | } 797 | list.head = None; 798 | } 799 | } 800 | } 801 | 802 | /// Splits the list into two after the current element. This will return a 803 | /// new list consisting of everything after the cursor, with the original 804 | /// list retaining everything before. 805 | /// 806 | /// If the cursor is pointing at the null object then the entire contents 807 | /// of the `SinglyLinkedList` are moved. 808 | #[inline] 809 | pub fn split_after(&mut self) -> SinglyLinkedList 810 | where 811 | A: Clone, 812 | { 813 | if let Some(current) = self.current { 814 | unsafe { 815 | let list = SinglyLinkedList { 816 | head: self.list.adapter.link_ops().next(current), 817 | adapter: self.list.adapter.clone(), 818 | }; 819 | self.list.adapter.link_ops_mut().set_next(current, None); 820 | list 821 | } 822 | } else { 823 | let list = SinglyLinkedList { 824 | head: self.list.head, 825 | adapter: self.list.adapter.clone(), 826 | }; 827 | self.list.head = None; 828 | list 829 | } 830 | } 831 | 832 | /// Consumes `CursorMut` and returns a reference to the object that 833 | /// the cursor is currently pointing to. Unlike [get](Self::get), 834 | /// the returned reference's lifetime is tied to `SinglyLinkedList`'s lifetime. 835 | /// 836 | /// This returns None if the cursor is currently pointing to the null object. 837 | #[inline] 838 | pub fn into_ref(self) -> Option<&'a ::Value> { 839 | Some(unsafe { &*self.list.adapter.get_value(self.current?) }) 840 | } 841 | } 842 | 843 | /// A cursor with ownership over the `SinglyLinkedList` it points into. 844 | pub struct CursorOwning 845 | where 846 | A::LinkOps: SinglyLinkedListOps, 847 | { 848 | current: Option<::LinkPtr>, 849 | list: SinglyLinkedList, 850 | } 851 | 852 | impl CursorOwning 853 | where 854 | A::LinkOps: SinglyLinkedListOps, 855 | { 856 | /// Consumes self and returns the inner `SinglyLinkedList`. 857 | #[inline] 858 | pub fn into_inner(self) -> SinglyLinkedList { 859 | self.list 860 | } 861 | 862 | /// Returns a read-only cursor pointing to the current element. 863 | /// 864 | /// The lifetime of the returned `Cursor` is bound to that of the 865 | /// `CursorOwning`, which means it cannot outlive the `CursorOwning` and that the 866 | /// `CursorOwning` is frozen for the lifetime of the `Cursor`. 867 | /// 868 | /// Mutations of the returned cursor are _not_ reflected in the original. 869 | #[inline] 870 | pub fn as_cursor(&self) -> Cursor<'_, A> { 871 | Cursor { 872 | current: self.current, 873 | list: &self.list, 874 | } 875 | } 876 | 877 | /// Perform action with mutable reference to the cursor. 878 | /// 879 | /// All mutations of the cursor are reflected in the original. 880 | #[inline] 881 | pub fn with_cursor_mut(&mut self, f: impl FnOnce(&mut CursorMut<'_, A>) -> T) -> T { 882 | let mut cursor = CursorMut { 883 | current: self.current, 884 | list: &mut self.list, 885 | }; 886 | let ret = f(&mut cursor); 887 | self.current = cursor.current; 888 | ret 889 | } 890 | } 891 | unsafe impl Send for CursorOwning 892 | where 893 | SinglyLinkedList: Send, 894 | A::LinkOps: SinglyLinkedListOps, 895 | { 896 | } 897 | 898 | // ============================================================================= 899 | // SinglyLinkedList 900 | // ============================================================================= 901 | 902 | /// An intrusive singly-linked list. 903 | /// 904 | /// When this collection is dropped, all elements linked into it will be 905 | /// converted back to owned pointers and dropped. 906 | pub struct SinglyLinkedList 907 | where 908 | A::LinkOps: SinglyLinkedListOps, 909 | { 910 | head: Option<::LinkPtr>, 911 | adapter: A, 912 | } 913 | 914 | impl SinglyLinkedList 915 | where 916 | A::LinkOps: SinglyLinkedListOps, 917 | { 918 | #[inline] 919 | fn node_from_value( 920 | &mut self, 921 | val: ::Pointer, 922 | ) -> ::LinkPtr { 923 | use link_ops::LinkOps; 924 | 925 | unsafe { 926 | let raw = self.adapter.pointer_ops().into_raw(val); 927 | let link = self.adapter.get_link(raw); 928 | 929 | if !self.adapter.link_ops_mut().acquire_link(link) { 930 | // convert the node back into a pointer 931 | self.adapter.pointer_ops().from_raw(raw); 932 | 933 | panic!("attempted to insert an object that is already linked"); 934 | } 935 | 936 | link 937 | } 938 | } 939 | 940 | /// Creates an empty `SinglyLinkedList`. 941 | #[cfg(not(feature = "nightly"))] 942 | #[inline] 943 | pub fn new(adapter: A) -> SinglyLinkedList { 944 | SinglyLinkedList { 945 | head: None, 946 | adapter, 947 | } 948 | } 949 | 950 | /// Creates an empty `SinglyLinkedList`. 951 | #[cfg(feature = "nightly")] 952 | #[inline] 953 | pub const fn new(adapter: A) -> SinglyLinkedList { 954 | SinglyLinkedList { 955 | head: None, 956 | adapter, 957 | } 958 | } 959 | 960 | /// Returns `true` if the `SinglyLinkedList` is empty. 961 | #[inline] 962 | pub fn is_empty(&self) -> bool { 963 | self.head.is_none() 964 | } 965 | 966 | /// Returns a null `Cursor` for this list. 967 | #[inline] 968 | pub fn cursor(&self) -> Cursor<'_, A> { 969 | Cursor { 970 | current: None, 971 | list: self, 972 | } 973 | } 974 | 975 | /// Returns a null `CursorMut` for this list. 976 | #[inline] 977 | pub fn cursor_mut(&mut self) -> CursorMut<'_, A> { 978 | CursorMut { 979 | current: None, 980 | list: self, 981 | } 982 | } 983 | 984 | /// Returns a null `CursorOwning` for this list. 985 | #[inline] 986 | pub fn cursor_owning(self) -> CursorOwning { 987 | CursorOwning { 988 | current: None, 989 | list: self, 990 | } 991 | } 992 | 993 | /// Creates a `Cursor` from a pointer to an element. 994 | /// 995 | /// # Safety 996 | /// 997 | /// `ptr` must be a pointer to an object that is part of this list. 998 | #[inline] 999 | pub unsafe fn cursor_from_ptr( 1000 | &self, 1001 | ptr: *const ::Value, 1002 | ) -> Cursor<'_, A> { 1003 | Cursor { 1004 | current: Some(self.adapter.get_link(ptr)), 1005 | list: self, 1006 | } 1007 | } 1008 | 1009 | /// Creates a `CursorMut` from a pointer to an element. 1010 | /// 1011 | /// # Safety 1012 | /// 1013 | /// `ptr` must be a pointer to an object that is part of this list. 1014 | #[inline] 1015 | pub unsafe fn cursor_mut_from_ptr( 1016 | &mut self, 1017 | ptr: *const ::Value, 1018 | ) -> CursorMut<'_, A> { 1019 | CursorMut { 1020 | current: Some(self.adapter.get_link(ptr)), 1021 | list: self, 1022 | } 1023 | } 1024 | 1025 | /// Creates a `CursorOwning` from a pointer to an element. 1026 | /// 1027 | /// # Safety 1028 | /// 1029 | /// `ptr` must be a pointer to an object that is part of this list. 1030 | #[inline] 1031 | pub unsafe fn cursor_owning_from_ptr( 1032 | self, 1033 | ptr: *const ::Value, 1034 | ) -> CursorOwning { 1035 | CursorOwning { 1036 | current: Some(self.adapter.get_link(ptr)), 1037 | list: self, 1038 | } 1039 | } 1040 | 1041 | /// Returns a `Cursor` pointing to the first element of the list. If the 1042 | /// list is empty then a null cursor is returned. 1043 | #[inline] 1044 | pub fn front(&self) -> Cursor<'_, A> { 1045 | let mut cursor = self.cursor(); 1046 | cursor.move_next(); 1047 | cursor 1048 | } 1049 | 1050 | /// Returns a `CursorMut` pointing to the first element of the list. If the 1051 | /// the list is empty then a null cursor is returned. 1052 | #[inline] 1053 | pub fn front_mut(&mut self) -> CursorMut<'_, A> { 1054 | let mut cursor = self.cursor_mut(); 1055 | cursor.move_next(); 1056 | cursor 1057 | } 1058 | 1059 | /// Returns a `CursorOwning` pointing to the first element of the list. If the 1060 | /// the list is empty then a null cursor is returned. 1061 | #[inline] 1062 | pub fn front_owning(self) -> CursorOwning { 1063 | let mut cursor = self.cursor_owning(); 1064 | cursor.with_cursor_mut(|c| c.move_next()); 1065 | cursor 1066 | } 1067 | 1068 | /// Gets an iterator over the objects in the `SinglyLinkedList`. 1069 | #[inline] 1070 | pub fn iter(&self) -> Iter<'_, A> { 1071 | Iter { 1072 | current: self.head, 1073 | list: self, 1074 | } 1075 | } 1076 | 1077 | /// Removes all elements from the `SinglyLinkedList`. 1078 | /// 1079 | /// This will unlink all object currently in the list, which requires 1080 | /// iterating through all elements in the `SinglyLinkedList`. Each element is 1081 | /// converted back to an owned pointer and then dropped. 1082 | #[inline] 1083 | pub fn clear(&mut self) { 1084 | use link_ops::LinkOps; 1085 | 1086 | let mut current = self.head; 1087 | self.head = None; 1088 | while let Some(x) = current { 1089 | unsafe { 1090 | let next = self.adapter.link_ops().next(x); 1091 | self.adapter.link_ops_mut().release_link(x); 1092 | self.adapter 1093 | .pointer_ops() 1094 | .from_raw(self.adapter.get_value(x)); 1095 | current = next; 1096 | } 1097 | } 1098 | } 1099 | 1100 | /// Empties the `SinglyLinkedList` without unlinking or freeing objects in it. 1101 | /// 1102 | /// Since this does not unlink any objects, any attempts to link these 1103 | /// objects into another `SinglyLinkedList` will fail but will not cause any 1104 | /// memory unsafety. To unlink those objects manually, you must call the 1105 | /// `force_unlink` function on them. 1106 | #[inline] 1107 | pub fn fast_clear(&mut self) { 1108 | self.head = None; 1109 | } 1110 | 1111 | /// Takes all the elements out of the `SinglyLinkedList`, leaving it empty. 1112 | /// The taken elements are returned as a new `SinglyLinkedList`. 1113 | #[inline] 1114 | pub fn take(&mut self) -> SinglyLinkedList 1115 | where 1116 | A: Clone, 1117 | { 1118 | let list = SinglyLinkedList { 1119 | head: self.head, 1120 | adapter: self.adapter.clone(), 1121 | }; 1122 | self.head = None; 1123 | list 1124 | } 1125 | 1126 | /// Inserts a new element at the start of the `SinglyLinkedList`. 1127 | #[inline] 1128 | pub fn push_front(&mut self, val: ::Pointer) { 1129 | self.cursor_mut().insert_after(val); 1130 | } 1131 | 1132 | /// Removes the first element of the `SinglyLinkedList`. 1133 | /// 1134 | /// This returns `None` if the `SinglyLinkedList` is empty. 1135 | #[inline] 1136 | pub fn pop_front(&mut self) -> Option<::Pointer> { 1137 | self.cursor_mut().remove_next() 1138 | } 1139 | } 1140 | 1141 | // Allow read-only access to values from multiple threads 1142 | unsafe impl Sync for SinglyLinkedList 1143 | where 1144 | ::Value: Sync, 1145 | A::LinkOps: SinglyLinkedListOps, 1146 | { 1147 | } 1148 | 1149 | // Allow sending to another thread if the ownership (represented by the ::Pointer owned 1150 | // pointer type) can be transferred to another thread. 1151 | unsafe impl Send for SinglyLinkedList 1152 | where 1153 | ::Pointer: Send, 1154 | A::LinkOps: SinglyLinkedListOps, 1155 | { 1156 | } 1157 | 1158 | // Drop all owned pointers if the collection is dropped 1159 | impl Drop for SinglyLinkedList 1160 | where 1161 | A::LinkOps: SinglyLinkedListOps, 1162 | { 1163 | #[inline] 1164 | fn drop(&mut self) { 1165 | self.clear(); 1166 | } 1167 | } 1168 | 1169 | impl IntoIterator for SinglyLinkedList 1170 | where 1171 | A::LinkOps: SinglyLinkedListOps, 1172 | { 1173 | type Item = ::Pointer; 1174 | type IntoIter = IntoIter; 1175 | 1176 | #[inline] 1177 | fn into_iter(self) -> IntoIter { 1178 | IntoIter { list: self } 1179 | } 1180 | } 1181 | 1182 | impl<'a, A: Adapter + 'a> IntoIterator for &'a SinglyLinkedList 1183 | where 1184 | A::LinkOps: SinglyLinkedListOps, 1185 | { 1186 | type Item = &'a ::Value; 1187 | type IntoIter = Iter<'a, A>; 1188 | 1189 | #[inline] 1190 | fn into_iter(self) -> Iter<'a, A> { 1191 | self.iter() 1192 | } 1193 | } 1194 | 1195 | impl Default for SinglyLinkedList 1196 | where 1197 | A::LinkOps: SinglyLinkedListOps, 1198 | { 1199 | fn default() -> SinglyLinkedList { 1200 | SinglyLinkedList::new(A::default()) 1201 | } 1202 | } 1203 | 1204 | impl fmt::Debug for SinglyLinkedList 1205 | where 1206 | A::LinkOps: SinglyLinkedListOps, 1207 | ::Value: fmt::Debug, 1208 | { 1209 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 1210 | f.debug_list().entries(self.iter()).finish() 1211 | } 1212 | } 1213 | 1214 | // ============================================================================= 1215 | // Iter 1216 | // ============================================================================= 1217 | 1218 | /// An iterator over references to the items of a `SinglyLinkedList`. 1219 | pub struct Iter<'a, A: Adapter> 1220 | where 1221 | A::LinkOps: SinglyLinkedListOps, 1222 | { 1223 | current: Option<::LinkPtr>, 1224 | list: &'a SinglyLinkedList, 1225 | } 1226 | impl<'a, A: Adapter + 'a> Iterator for Iter<'a, A> 1227 | where 1228 | A::LinkOps: SinglyLinkedListOps, 1229 | { 1230 | type Item = &'a ::Value; 1231 | 1232 | #[inline] 1233 | fn next(&mut self) -> Option<&'a ::Value> { 1234 | let current = self.current?; 1235 | 1236 | self.current = unsafe { self.list.adapter.link_ops().next(current) }; 1237 | Some(unsafe { &*self.list.adapter.get_value(current) }) 1238 | } 1239 | } 1240 | impl<'a, A: Adapter + 'a> Clone for Iter<'a, A> 1241 | where 1242 | A::LinkOps: SinglyLinkedListOps, 1243 | { 1244 | #[inline] 1245 | fn clone(&self) -> Iter<'a, A> { 1246 | Iter { 1247 | current: self.current, 1248 | list: self.list, 1249 | } 1250 | } 1251 | } 1252 | 1253 | // ============================================================================= 1254 | // IntoIter 1255 | // ============================================================================= 1256 | 1257 | /// An iterator which consumes a `SinglyLinkedList`. 1258 | pub struct IntoIter 1259 | where 1260 | A::LinkOps: SinglyLinkedListOps, 1261 | { 1262 | list: SinglyLinkedList, 1263 | } 1264 | impl Iterator for IntoIter 1265 | where 1266 | A::LinkOps: SinglyLinkedListOps, 1267 | { 1268 | type Item = ::Pointer; 1269 | 1270 | #[inline] 1271 | fn next(&mut self) -> Option<::Pointer> { 1272 | self.list.pop_front() 1273 | } 1274 | } 1275 | 1276 | // ============================================================================= 1277 | // Tests 1278 | // ============================================================================= 1279 | 1280 | #[cfg(test)] 1281 | mod tests { 1282 | use alloc::boxed::Box; 1283 | 1284 | use crate::UnsafeRef; 1285 | 1286 | use super::{CursorOwning, Link, SinglyLinkedList}; 1287 | use std::fmt; 1288 | use std::format; 1289 | use std::rc::Rc; 1290 | use std::vec::Vec; 1291 | 1292 | struct Obj { 1293 | link1: Link, 1294 | link2: Link, 1295 | value: u32, 1296 | } 1297 | impl fmt::Debug for Obj { 1298 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 1299 | write!(f, "{}", self.value) 1300 | } 1301 | } 1302 | intrusive_adapter!(RcObjAdapter1 = Rc: Obj { link1: Link }); 1303 | intrusive_adapter!(RcObjAdapter2 = Rc: Obj { link2: Link }); 1304 | intrusive_adapter!(UnsafeRefObjAdapter1 = UnsafeRef: Obj { link1: Link }); 1305 | 1306 | fn make_rc_obj(value: u32) -> Rc { 1307 | Rc::new(make_obj(value)) 1308 | } 1309 | fn make_obj(value: u32) -> Obj { 1310 | Obj { 1311 | link1: Link::new(), 1312 | link2: Link::default(), 1313 | value, 1314 | } 1315 | } 1316 | 1317 | #[test] 1318 | fn test_link() { 1319 | let a = make_rc_obj(1); 1320 | assert!(!a.link1.is_linked()); 1321 | assert!(!a.link2.is_linked()); 1322 | 1323 | let mut b = SinglyLinkedList::::default(); 1324 | assert!(b.is_empty()); 1325 | 1326 | b.push_front(a.clone()); 1327 | assert!(!b.is_empty()); 1328 | assert!(a.link1.is_linked()); 1329 | assert!(!a.link2.is_linked()); 1330 | assert_eq!(format!("{:?}", a.link1), "linked"); 1331 | assert_eq!(format!("{:?}", a.link2), "unlinked"); 1332 | 1333 | assert_eq!( 1334 | b.pop_front().unwrap().as_ref() as *const _, 1335 | a.as_ref() as *const _ 1336 | ); 1337 | assert!(b.is_empty()); 1338 | assert!(!a.link1.is_linked()); 1339 | assert!(!a.link2.is_linked()); 1340 | } 1341 | 1342 | #[test] 1343 | fn test_cursor() { 1344 | let a = make_rc_obj(1); 1345 | let b = make_rc_obj(2); 1346 | let c = make_rc_obj(3); 1347 | 1348 | let mut l = SinglyLinkedList::new(RcObjAdapter1::new()); 1349 | let mut cur = l.cursor_mut(); 1350 | assert!(cur.is_null()); 1351 | assert!(cur.get().is_none()); 1352 | assert!(cur.remove_next().is_none()); 1353 | assert_eq!( 1354 | cur.replace_next_with(a.clone()).unwrap_err().as_ref() as *const _, 1355 | a.as_ref() as *const _ 1356 | ); 1357 | 1358 | cur.insert_after(c.clone()); 1359 | cur.insert_after(a.clone()); 1360 | cur.move_next(); 1361 | cur.insert_after(b.clone()); 1362 | cur.move_next(); 1363 | cur.move_next(); 1364 | assert!(cur.peek_next().is_null()); 1365 | cur.move_next(); 1366 | assert!(cur.is_null()); 1367 | 1368 | cur.move_next(); 1369 | assert!(!cur.is_null()); 1370 | assert_eq!(cur.get().unwrap() as *const _, a.as_ref() as *const _); 1371 | 1372 | { 1373 | let mut cur2 = cur.as_cursor(); 1374 | assert_eq!(cur2.get().unwrap() as *const _, a.as_ref() as *const _); 1375 | assert_eq!(cur2.peek_next().get().unwrap().value, 2); 1376 | cur2.move_next(); 1377 | assert_eq!(cur2.get().unwrap().value, 2); 1378 | cur2.move_next(); 1379 | assert_eq!(cur2.get().unwrap() as *const _, c.as_ref() as *const _); 1380 | cur2.move_next(); 1381 | assert!(cur2.is_null()); 1382 | assert!(cur2.clone().get().is_none()); 1383 | } 1384 | assert_eq!(cur.get().unwrap() as *const _, a.as_ref() as *const _); 1385 | 1386 | assert_eq!( 1387 | cur.remove_next().unwrap().as_ref() as *const _, 1388 | b.as_ref() as *const _ 1389 | ); 1390 | assert_eq!(cur.get().unwrap() as *const _, a.as_ref() as *const _); 1391 | cur.insert_after(b.clone()); 1392 | assert_eq!(cur.get().unwrap() as *const _, a.as_ref() as *const _); 1393 | cur.move_next(); 1394 | assert_eq!(cur.get().unwrap() as *const _, b.as_ref() as *const _); 1395 | assert_eq!( 1396 | cur.remove_next().unwrap().as_ref() as *const _, 1397 | c.as_ref() as *const _ 1398 | ); 1399 | assert!(!c.link1.is_linked()); 1400 | assert!(a.link1.is_linked()); 1401 | assert_eq!(cur.get().unwrap() as *const _, b.as_ref() as *const _); 1402 | cur.move_next(); 1403 | assert!(cur.is_null()); 1404 | assert_eq!( 1405 | cur.replace_next_with(c.clone()).unwrap().as_ref() as *const _, 1406 | a.as_ref() as *const _ 1407 | ); 1408 | assert!(!a.link1.is_linked()); 1409 | assert!(c.link1.is_linked()); 1410 | assert!(cur.is_null()); 1411 | cur.move_next(); 1412 | assert_eq!(cur.get().unwrap() as *const _, c.as_ref() as *const _); 1413 | assert_eq!( 1414 | cur.replace_next_with(a.clone()).unwrap().as_ref() as *const _, 1415 | b.as_ref() as *const _ 1416 | ); 1417 | assert!(a.link1.is_linked()); 1418 | assert!(!b.link1.is_linked()); 1419 | assert!(c.link1.is_linked()); 1420 | assert_eq!(cur.get().unwrap() as *const _, c.as_ref() as *const _); 1421 | } 1422 | 1423 | #[test] 1424 | fn test_cursor_owning() { 1425 | struct Container { 1426 | cur: CursorOwning, 1427 | } 1428 | 1429 | let mut l = SinglyLinkedList::new(RcObjAdapter1::new()); 1430 | l.push_front(make_rc_obj(1)); 1431 | l.push_front(make_rc_obj(2)); 1432 | l.push_front(make_rc_obj(3)); 1433 | l.push_front(make_rc_obj(4)); 1434 | let mut con = Container { 1435 | cur: l.cursor_owning(), 1436 | }; 1437 | assert!(con.cur.as_cursor().is_null()); 1438 | 1439 | con.cur = con.cur.into_inner().front_owning(); 1440 | assert_eq!(con.cur.as_cursor().get().unwrap().value, 4); 1441 | 1442 | con.cur.with_cursor_mut(|c| c.move_next()); 1443 | assert_eq!(con.cur.as_cursor().get().unwrap().value, 3); 1444 | } 1445 | 1446 | #[test] 1447 | fn test_split_splice() { 1448 | let mut l1 = SinglyLinkedList::new(RcObjAdapter1::new()); 1449 | let mut l2 = SinglyLinkedList::new(RcObjAdapter1::new()); 1450 | let mut l3 = SinglyLinkedList::new(RcObjAdapter1::new()); 1451 | 1452 | let a = make_rc_obj(1); 1453 | let b = make_rc_obj(2); 1454 | let c = make_rc_obj(3); 1455 | let d = make_rc_obj(4); 1456 | l1.cursor_mut().insert_after(d); 1457 | l1.cursor_mut().insert_after(c); 1458 | l1.cursor_mut().insert_after(b); 1459 | l1.cursor_mut().insert_after(a); 1460 | assert_eq!(l1.iter().map(|x| x.value).collect::>(), [1, 2, 3, 4]); 1461 | assert_eq!(l2.iter().map(|x| x.value).collect::>(), []); 1462 | assert_eq!(l3.iter().map(|x| x.value).collect::>(), []); 1463 | { 1464 | let mut cur = l1.front_mut(); 1465 | cur.move_next(); 1466 | l2 = cur.split_after(); 1467 | } 1468 | assert_eq!(l1.iter().map(|x| x.value).collect::>(), [1, 2]); 1469 | assert_eq!(l2.iter().map(|x| x.value).collect::>(), [3, 4]); 1470 | assert_eq!(l3.iter().map(|x| x.value).collect::>(), []); 1471 | { 1472 | let mut cur = l2.front_mut(); 1473 | l3 = cur.split_after(); 1474 | } 1475 | assert_eq!(l1.iter().map(|x| x.value).collect::>(), [1, 2]); 1476 | assert_eq!(l2.iter().map(|x| x.value).collect::>(), [3]); 1477 | assert_eq!(l3.iter().map(|x| x.value).collect::>(), [4]); 1478 | { 1479 | let mut cur = l1.front_mut(); 1480 | cur.splice_after(l2.take()); 1481 | } 1482 | assert_eq!(l1.iter().map(|x| x.value).collect::>(), [1, 3, 2]); 1483 | assert_eq!(l2.iter().map(|x| x.value).collect::>(), []); 1484 | assert_eq!(l3.iter().map(|x| x.value).collect::>(), [4]); 1485 | { 1486 | let mut cur = l1.cursor_mut(); 1487 | cur.splice_after(l3.take()); 1488 | } 1489 | assert_eq!(l1.iter().map(|x| x.value).collect::>(), [4, 1, 3, 2]); 1490 | assert_eq!(l2.iter().map(|x| x.value).collect::>(), []); 1491 | assert_eq!(l3.iter().map(|x| x.value).collect::>(), []); 1492 | { 1493 | let mut cur = l1.cursor_mut(); 1494 | l2 = cur.split_after(); 1495 | } 1496 | assert_eq!(l1.iter().map(|x| x.value).collect::>(), []); 1497 | assert_eq!(l2.iter().map(|x| x.value).collect::>(), [4, 1, 3, 2]); 1498 | assert_eq!(l3.iter().map(|x| x.value).collect::>(), []); 1499 | { 1500 | let mut cur = l2.front_mut(); 1501 | cur.move_next(); 1502 | l3 = cur.split_after(); 1503 | } 1504 | assert_eq!(l1.iter().map(|x| x.value).collect::>(), []); 1505 | assert_eq!(l2.iter().map(|x| x.value).collect::>(), [4, 1]); 1506 | assert_eq!(l3.iter().map(|x| x.value).collect::>(), [3, 2]); 1507 | { 1508 | let mut cur = l2.front_mut(); 1509 | cur.splice_after(l3.take()); 1510 | } 1511 | assert_eq!(l1.iter().map(|x| x.value).collect::>(), []); 1512 | assert_eq!(l2.iter().map(|x| x.value).collect::>(), [4, 3, 2, 1]); 1513 | assert_eq!(l3.iter().map(|x| x.value).collect::>(), []); 1514 | { 1515 | let mut cur = l3.cursor_mut(); 1516 | cur.splice_after(l2.take()); 1517 | } 1518 | assert_eq!(l1.iter().map(|x| x.value).collect::>(), []); 1519 | assert_eq!(l2.iter().map(|x| x.value).collect::>(), []); 1520 | assert_eq!(l3.iter().map(|x| x.value).collect::>(), [4, 3, 2, 1]); 1521 | { 1522 | let mut cur = l3.front_mut(); 1523 | cur.move_next(); 1524 | l2 = cur.split_after(); 1525 | } 1526 | assert_eq!(l1.iter().map(|x| x.value).collect::>(), []); 1527 | assert_eq!(l2.iter().map(|x| x.value).collect::>(), [2, 1]); 1528 | assert_eq!(l3.iter().map(|x| x.value).collect::>(), [4, 3]); 1529 | { 1530 | let mut cur = l2.front_mut(); 1531 | cur.move_next(); 1532 | cur.splice_after(l3.take()); 1533 | } 1534 | assert_eq!(l1.iter().map(|x| x.value).collect::>(), []); 1535 | assert_eq!(l2.iter().map(|x| x.value).collect::>(), [2, 1, 4, 3]); 1536 | assert_eq!(l3.iter().map(|x| x.value).collect::>(), []); 1537 | } 1538 | 1539 | #[test] 1540 | fn test_iter() { 1541 | let mut l = SinglyLinkedList::new(RcObjAdapter1::new()); 1542 | let a = make_rc_obj(1); 1543 | let b = make_rc_obj(2); 1544 | let c = make_rc_obj(3); 1545 | let d = make_rc_obj(4); 1546 | l.cursor_mut().insert_after(d.clone()); 1547 | l.cursor_mut().insert_after(c.clone()); 1548 | l.cursor_mut().insert_after(b.clone()); 1549 | l.cursor_mut().insert_after(a.clone()); 1550 | 1551 | assert_eq!(l.front().get().unwrap().value, 1); 1552 | unsafe { 1553 | assert_eq!(l.cursor_from_ptr(b.as_ref()).get().unwrap().value, 2); 1554 | assert_eq!(l.cursor_mut_from_ptr(c.as_ref()).get().unwrap().value, 3); 1555 | } 1556 | 1557 | let mut v = Vec::new(); 1558 | for x in &l { 1559 | v.push(x.value); 1560 | } 1561 | assert_eq!(v, [1, 2, 3, 4]); 1562 | assert_eq!( 1563 | l.iter().clone().map(|x| x.value).collect::>(), 1564 | [1, 2, 3, 4] 1565 | ); 1566 | assert_eq!(l.iter().map(|x| x.value).collect::>(), [1, 2, 3, 4]); 1567 | 1568 | assert_eq!(format!("{:?}", l), "[1, 2, 3, 4]"); 1569 | 1570 | let mut v = Vec::new(); 1571 | for x in l.take() { 1572 | v.push(x.value); 1573 | } 1574 | assert_eq!(v, [1, 2, 3, 4]); 1575 | assert!(l.is_empty()); 1576 | assert!(!a.link1.is_linked()); 1577 | assert!(!b.link1.is_linked()); 1578 | assert!(!c.link1.is_linked()); 1579 | assert!(!d.link1.is_linked()); 1580 | 1581 | l.cursor_mut().insert_after(d.clone()); 1582 | l.cursor_mut().insert_after(c.clone()); 1583 | l.cursor_mut().insert_after(b.clone()); 1584 | l.cursor_mut().insert_after(a.clone()); 1585 | l.clear(); 1586 | assert!(l.is_empty()); 1587 | assert!(!a.link1.is_linked()); 1588 | assert!(!b.link1.is_linked()); 1589 | assert!(!c.link1.is_linked()); 1590 | assert!(!d.link1.is_linked()); 1591 | } 1592 | 1593 | #[test] 1594 | fn test_multi_list() { 1595 | let mut l1 = SinglyLinkedList::new(RcObjAdapter1::new()); 1596 | let mut l2 = SinglyLinkedList::new(RcObjAdapter2::new()); 1597 | let a = make_rc_obj(1); 1598 | let b = make_rc_obj(2); 1599 | let c = make_rc_obj(3); 1600 | let d = make_rc_obj(4); 1601 | l1.cursor_mut().insert_after(d.clone()); 1602 | l1.cursor_mut().insert_after(c.clone()); 1603 | l1.cursor_mut().insert_after(b.clone()); 1604 | l1.cursor_mut().insert_after(a.clone()); 1605 | l2.cursor_mut().insert_after(a); 1606 | l2.cursor_mut().insert_after(b); 1607 | l2.cursor_mut().insert_after(c); 1608 | l2.cursor_mut().insert_after(d); 1609 | assert_eq!(l1.iter().map(|x| x.value).collect::>(), [1, 2, 3, 4]); 1610 | assert_eq!(l2.iter().map(|x| x.value).collect::>(), [4, 3, 2, 1]); 1611 | } 1612 | 1613 | #[test] 1614 | fn test_fast_clear_force_unlink() { 1615 | let mut l = SinglyLinkedList::new(UnsafeRefObjAdapter1::new()); 1616 | let a = UnsafeRef::from_box(Box::new(make_obj(1))); 1617 | let b = UnsafeRef::from_box(Box::new(make_obj(2))); 1618 | let c = UnsafeRef::from_box(Box::new(make_obj(3))); 1619 | l.cursor_mut().insert_after(a.clone()); 1620 | l.cursor_mut().insert_after(b.clone()); 1621 | l.cursor_mut().insert_after(c.clone()); 1622 | 1623 | l.fast_clear(); 1624 | assert!(l.is_empty()); 1625 | 1626 | unsafe { 1627 | assert!(a.link1.is_linked()); 1628 | assert!(b.link1.is_linked()); 1629 | assert!(c.link1.is_linked()); 1630 | 1631 | a.link1.force_unlink(); 1632 | b.link1.force_unlink(); 1633 | c.link1.force_unlink(); 1634 | 1635 | assert!(l.is_empty()); 1636 | 1637 | assert!(!a.link1.is_linked()); 1638 | assert!(!b.link1.is_linked()); 1639 | assert!(!c.link1.is_linked()); 1640 | } 1641 | 1642 | unsafe { 1643 | UnsafeRef::into_box(a); 1644 | UnsafeRef::into_box(b); 1645 | UnsafeRef::into_box(c); 1646 | } 1647 | } 1648 | 1649 | #[test] 1650 | fn test_non_static() { 1651 | #[derive(Clone)] 1652 | struct Obj<'a, T> { 1653 | link: Link, 1654 | value: &'a T, 1655 | } 1656 | intrusive_adapter!(ObjAdapter<'a, T> = &'a Obj<'a, T>: Obj<'a, T> {link: Link} where T: 'a); 1657 | 1658 | let v = 5; 1659 | let a = Obj { 1660 | link: Link::new(), 1661 | value: &v, 1662 | }; 1663 | let b = a.clone(); 1664 | let mut l = SinglyLinkedList::new(ObjAdapter::new()); 1665 | l.cursor_mut().insert_after(&a); 1666 | l.cursor_mut().insert_after(&b); 1667 | assert_eq!(*l.front().get().unwrap().value, 5); 1668 | assert_eq!(*l.front().get().unwrap().value, 5); 1669 | } 1670 | 1671 | macro_rules! test_clone_pointer { 1672 | ($ptr: ident, $ptr_import: path) => { 1673 | use $ptr_import; 1674 | 1675 | #[derive(Clone)] 1676 | struct Obj { 1677 | link: Link, 1678 | value: usize, 1679 | } 1680 | intrusive_adapter!(ObjAdapter = $ptr: Obj { link: Link }); 1681 | 1682 | let a = $ptr::new(Obj { 1683 | link: Link::new(), 1684 | value: 5, 1685 | }); 1686 | let mut l = SinglyLinkedList::new(ObjAdapter::new()); 1687 | l.cursor_mut().insert_after(a.clone()); 1688 | assert_eq!(2, $ptr::strong_count(&a)); 1689 | 1690 | let pointer = l.front().clone_pointer().unwrap(); 1691 | assert_eq!(pointer.value, 5); 1692 | assert_eq!(3, $ptr::strong_count(&a)); 1693 | 1694 | l.clear(); 1695 | assert!(l.front().clone_pointer().is_none()); 1696 | }; 1697 | } 1698 | 1699 | #[test] 1700 | fn test_clone_pointer_rc() { 1701 | test_clone_pointer!(Rc, std::rc::Rc); 1702 | } 1703 | 1704 | #[test] 1705 | fn test_clone_pointer_arc() { 1706 | test_clone_pointer!(Arc, std::sync::Arc); 1707 | } 1708 | } 1709 | -------------------------------------------------------------------------------- /src/unchecked_option.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Amari Robinson 2 | // 3 | // Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be 6 | // copied, modified, or distributed except according to those terms. 7 | 8 | use core::hint; 9 | 10 | /// An extension trait on `Option`. 11 | pub trait UncheckedOptionExt { 12 | /// Returns the contained value. 13 | /// 14 | /// # Safety 15 | /// 16 | /// It is up to the caller to guarantee that the `Option` is `Some(v)`. 17 | /// Calling this when it is `None` causes undefined behavior. 18 | unsafe fn unwrap_unchecked(self) -> T; 19 | } 20 | 21 | impl UncheckedOptionExt for Option { 22 | #[inline] 23 | unsafe fn unwrap_unchecked(self) -> T { 24 | match self { 25 | Some(x) => x, 26 | None => { 27 | if cfg!(debug_assertions) { 28 | unreachable!() 29 | } else { 30 | hint::unreachable_unchecked() 31 | } 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/unsafe_ref.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Amanieu d'Antras 2 | // 3 | // Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be 6 | // copied, modified, or distributed except according to those terms. 7 | 8 | #[cfg(feature = "alloc")] 9 | use crate::alloc::boxed::Box; 10 | use core::borrow::Borrow; 11 | use core::fmt; 12 | use core::ops::Deref; 13 | use core::ptr::NonNull; 14 | 15 | /// Unchecked shared pointer 16 | /// 17 | /// This type acts like a `Rc` or `Arc` except that no reference count is 18 | /// maintained. Instead, the user is responsible for freeing the managed object 19 | /// once it is no longer in use. 20 | /// 21 | /// You must guarantee that an object managed by an `UnsafeRef` is not 22 | /// moved, dropped or accessed through a mutable reference as long as at least 23 | /// one `UnsafeRef` is pointing to it. 24 | pub struct UnsafeRef { 25 | ptr: NonNull, 26 | } 27 | 28 | impl UnsafeRef { 29 | /// Creates an `UnsafeRef` from a raw pointer 30 | /// 31 | /// # Safety 32 | /// 33 | /// You must ensure that the `UnsafeRef` guarantees are upheld. 34 | #[inline] 35 | pub unsafe fn from_raw(val: *const T) -> UnsafeRef { 36 | UnsafeRef { 37 | ptr: NonNull::new_unchecked(val as *mut _), 38 | } 39 | } 40 | 41 | /// Converts an `UnsafeRef` into a raw pointer 42 | #[inline] 43 | pub fn into_raw(ptr: Self) -> *mut T { 44 | ptr.ptr.as_ptr() 45 | } 46 | } 47 | 48 | #[cfg(feature = "alloc")] 49 | impl UnsafeRef { 50 | /// Creates an `UnsafeRef` from a `Box` 51 | #[inline] 52 | pub fn from_box(val: Box) -> UnsafeRef { 53 | unsafe { UnsafeRef::from_raw(Box::into_raw(val)) } 54 | } 55 | 56 | /// Converts an `UnsafeRef` into a `Box` 57 | /// 58 | /// # Safety 59 | /// 60 | /// You must ensure that this is the only `UnsafeRef` managing this 61 | /// object and that it is not currently a member of any intrusive 62 | /// collections. This operation is only valid if the `UnsafeRef` was 63 | /// created using `UnsafeRef::from_box`. 64 | #[inline] 65 | pub unsafe fn into_box(ptr: Self) -> Box { 66 | Box::from_raw(UnsafeRef::into_raw(ptr)) 67 | } 68 | } 69 | 70 | impl Clone for UnsafeRef { 71 | #[inline] 72 | fn clone(&self) -> UnsafeRef { 73 | UnsafeRef { ptr: self.ptr } 74 | } 75 | } 76 | 77 | impl Deref for UnsafeRef { 78 | type Target = T; 79 | 80 | #[inline] 81 | fn deref(&self) -> &T { 82 | self.as_ref() 83 | } 84 | } 85 | 86 | impl AsRef for UnsafeRef { 87 | #[inline] 88 | fn as_ref(&self) -> &T { 89 | unsafe { self.ptr.as_ref() } 90 | } 91 | } 92 | 93 | impl Borrow for UnsafeRef { 94 | #[inline] 95 | fn borrow(&self) -> &T { 96 | self.as_ref() 97 | } 98 | } 99 | 100 | impl fmt::Debug for UnsafeRef { 101 | #[inline] 102 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 103 | fmt::Debug::fmt(self.as_ref(), f) 104 | } 105 | } 106 | 107 | unsafe impl Send for UnsafeRef {} 108 | 109 | unsafe impl Sync for UnsafeRef {} 110 | --------------------------------------------------------------------------------