pub struct SinglyLinkedList<P, Tag = DefaultObjectTag, S = NonTrackingSize>{ /* private fields */ }Expand description
A singly linked list that supports intrusive nodes and different ownership semantics.
SinglyLinkedList is a layout-compatible analog to fbl::SinglyLinkedList in C++.
It allows managing singly linked lists of objects where the bookkeeping storage
(the node state) exists on the objects themselves, eliminating the need for
runtime allocation/deallocation to add or remove members.
The list stores pointers to the objects, and is parametrized by the pointer type P.
Supported pointer types are:
*mut T: Raw unmanaged pointers.- [
UniquePtr<T>] : Unique managed pointers. - [
RefPtr<T>] : Managed pointers to ref-counted objects.
§Ownership
- Lists of managed pointer types ([
UniquePtr], [RefPtr]) hold references to objects and follow the rules of the particular managed pointer patterns. Destroying or clearing a list of managed pointers will release the references to the objects. - Lists of unmanaged pointer types (
*mut T) perform no lifecycle management. It is up to the user to make sure that lifecycles are managed properly. As an added safety, a list of unmanaged pointers will assert if it is destroyed with elements still in it.
§Multiple Lists
Objects may exist in multiple lists simultaneously through the use of custom
trait tags. See SinglyLinkedListContainable for more details.
§Examples
§Example 1: A simple list of unmanaged pointers to Foo objects
use fbl::{SinglyLinkedList, SinglyLinkedListNode, SinglyLinkedListContainable};
#[derive(SinglyLinkedListContainable)]
struct Foo {
value: i32,
#[sll_node]
node: SinglyLinkedListNode<Foo>,
}
impl Foo {
fn new(value: i32) -> Self {
Self { value, node: SinglyLinkedListNode::new() }
}
}
fn test() {
let mut list = SinglyLinkedList::<*mut Foo>::new();
let mut foo1 = Foo::new(1);
let mut foo2 = Foo::new(2);
unsafe {
list.push_front_raw(&mut foo1);
list.push_front_raw(&mut foo2);
}
for foo in list.iter() {
println!("Value: {}", foo.value);
}
list.clear(); // Must clear before going out of scope if using raw pointers!
}§Example 2: A simple list of unique pointers to Foo objects
use fbl::{SinglyLinkedList, SinglyLinkedListNode, SinglyLinkedListContainable, UniquePtr};
#[derive(fbl::Recyclable, SinglyLinkedListContainable)]
struct Foo {
value: i32,
#[sll_node]
node: SinglyLinkedListNode<Foo>,
}
impl Foo {
fn new(value: i32) -> Self {
Self { value, node: SinglyLinkedListNode::new() }
}
}
fn test() {
let mut list = SinglyLinkedList::<UniquePtr<Foo>>::new();
let foo1 = UniquePtr::try_new(Foo::new(1)).unwrap();
let foo2 = UniquePtr::try_new(Foo::new(2)).unwrap();
list.push_front(foo1);
list.push_front(foo2);
for foo in list.iter() {
println!("Value: {}", foo.value);
}
// List drops here and cleans up objects automatically!
}§Example 3: An object in multiple lists
use fbl::{SinglyLinkedList, SinglyLinkedListNode, SinglyLinkedListContainable};
struct Tag2;
#[derive(SinglyLinkedListContainable)]
struct Foo {
value: i32,
#[sll_node]
node1: SinglyLinkedListNode<Foo>,
#[sll_node(tag = Tag2)]
node2: SinglyLinkedListNode<Foo>,
}
fn test() {
let mut list1 = SinglyLinkedList::<*mut Foo>::new();
let mut list2 = SinglyLinkedList::<*mut Foo, Tag2>::new();
let mut foo = Foo {
value: 42,
node1: SinglyLinkedListNode::new(),
node2: SinglyLinkedListNode::new(),
};
unsafe {
list1.push_front_raw(&mut foo);
list2.push_front_raw(&mut foo);
}
// ... access via both lists ...
list1.clear();
list2.clear();
}Implementations§
Source§impl<P, Tag, S> SinglyLinkedList<P, Tag, S>
impl<P, Tag, S> SinglyLinkedList<P, Tag, S>
Sourcepub fn front(&self) -> Option<&P::Target>
pub fn front(&self) -> Option<&P::Target>
Returns a reference to the first element of the list, or None if it is empty.
Sourcepub fn front_mut(&mut self) -> Option<&mut P::Target>
pub fn front_mut(&mut self) -> Option<&mut P::Target>
Returns a mutable reference to the first element of the list, or None if it is empty.
Sourcepub fn push_front(&mut self, ptr: P)where
P: ManagedPtr,
pub fn push_front(&mut self, ptr: P)where
P: ManagedPtr,
Sourcepub unsafe fn push_front_raw(&mut self, ptr: P)
pub unsafe fn push_front_raw(&mut self, ptr: P)
Sourcepub fn pop_front(&mut self) -> Option<P>
pub fn pop_front(&mut self) -> Option<P>
Removes and returns the first element of the list, or None if it is empty.
Sourcepub unsafe fn insert_after_raw(&mut self, pos: *mut P::Target, ptr: P)
pub unsafe fn insert_after_raw(&mut self, pos: *mut P::Target, ptr: P)
Inserts an element after the specified position.
For managed pointers, consider using [CursorMut::insert_after] for a safer alternative.
§Safety
The caller must ensure that pos is a valid pointer to an element in this list,
and that ptr is a valid pointer to an element not currently in any container.
Sourcepub unsafe fn erase_next_raw(&mut self, pos: *mut P::Target) -> Option<P>
pub unsafe fn erase_next_raw(&mut self, pos: *mut P::Target) -> Option<P>
Erases the element after the specified position.
For managed pointers, consider using [CursorMut::erase_next] for a safer alternative.
§Safety
The caller must ensure that pos is a valid pointer to an element in this list.
Sourcepub fn erase_if<F>(&mut self, f: F) -> Option<P>
pub fn erase_if<F>(&mut self, f: F) -> Option<P>
Finds the first element matching the predicate, removes it from the list,
and returns it. Returns None if no element matches.
Sourcepub fn replace_if<F>(&mut self, f: F, value: P) -> Option<P>
pub fn replace_if<F>(&mut self, f: F, value: P) -> Option<P>
Replaces the first element matching the predicate with value. Returns the replaced
element.
§Panics
Panics if the object is already in a container.
Sourcepub unsafe fn replace_if_raw<F>(&mut self, f: F, value: P) -> Option<P>
pub unsafe fn replace_if_raw<F>(&mut self, f: F, value: P) -> Option<P>
Sourcepub unsafe fn split_after_raw(&mut self, pos: *mut P::Target) -> Self
pub unsafe fn split_after_raw(&mut self, pos: *mut P::Target) -> Self
Splits the list after the specified position, returning a new list
containing the elements that followed pos.
§Safety
The caller must ensure that pos is a valid pointer to an element in this list.
Sourcepub fn cursor_mut(&mut self) -> CursorMut<'_, P, Tag, S>
pub fn cursor_mut(&mut self) -> CursorMut<'_, P, Tag, S>
Returns a cursor positioned at the front of the list.
Sourcepub fn size_slow(&self) -> usize
pub fn size_slow(&self) -> usize
Calculates the size of the list by iterating through all elements. O(N) time complexity.
Source§impl<P, Tag> SinglyLinkedList<P, Tag, TrackingSize>
impl<P, Tag> SinglyLinkedList<P, Tag, TrackingSize>
Trait Implementations§
Source§impl<P, Tag, S> Debug for SinglyLinkedList<P, Tag, S>
impl<P, Tag, S> Debug for SinglyLinkedList<P, Tag, S>
Source§impl<P, Tag, S> Drop for SinglyLinkedList<P, Tag, S>
impl<P, Tag, S> Drop for SinglyLinkedList<P, Tag, S>
Auto Trait Implementations§
impl<P, Tag, S> Freeze for SinglyLinkedList<P, Tag, S>where
S: Freeze,
impl<P, Tag, S> RefUnwindSafe for SinglyLinkedList<P, Tag, S>where
S: RefUnwindSafe,
<P as PtrTraits>::Target: RefUnwindSafe,
P: RefUnwindSafe,
Tag: RefUnwindSafe,
impl<P, Tag = DefaultObjectTag, S = NonTrackingSize> !Send for SinglyLinkedList<P, Tag, S>
impl<P, Tag = DefaultObjectTag, S = NonTrackingSize> !Sync for SinglyLinkedList<P, Tag, S>
impl<P, Tag, S> Unpin for SinglyLinkedList<P, Tag, S>
impl<P, Tag, S> UnsafeUnpin for SinglyLinkedList<P, Tag, S>where
S: UnsafeUnpin,
impl<P, Tag, S> UnwindSafe for SinglyLinkedList<P, Tag, S>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> PinInit<T> for T
impl<T> PinInit<T> for T
Source§unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), Infallible>
unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), Infallible>
slot. Read more