Skip to main content

SinglyLinkedList

Struct SinglyLinkedList 

Source
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:

  1. *mut T : Raw unmanaged pointers.
  2. [UniquePtr<T>] : Unique managed pointers.
  3. [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>

Source

pub const fn new() -> Self

Creates a new, empty list.

Source

pub fn is_empty(&self) -> bool

Returns true if the list is empty.

Source

pub fn front(&self) -> Option<&P::Target>

Returns a reference to the first element of the list, or None if it is empty.

Source

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.

Source

pub fn push_front(&mut self, ptr: P)
where P: ManagedPtr,

Pushes an element to the front of the list.

§Panics

Panics if the object is already in a container.

Source

pub unsafe fn push_front_raw(&mut self, ptr: P)

Pushes an element to the front of the list.

For managed pointers, use the safe [push_front] instead.

§Panics

Panics if the object is already in a container.

§Safety

The caller must ensure that ptr is a valid pointer to a T and that the object outlives the reference from the list.

Source

pub fn pop_front(&mut self) -> Option<P>

Removes and returns the first element of the list, or None if it is empty.

Source

pub fn clear(&mut self)

Removes all elements from the list.

Source

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.

Source

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.

Source

pub fn swap(&mut self, other: &mut Self)

Swaps the contents of this list with another list.

Source

pub fn erase_if<F>(&mut self, f: F) -> Option<P>
where F: FnMut(&P::Target) -> bool,

Finds the first element matching the predicate, removes it from the list, and returns it. Returns None if no element matches.

Source

pub fn replace_if<F>(&mut self, f: F, value: P) -> Option<P>
where F: FnMut(&P::Target) -> bool, P: ManagedPtr,

Replaces the first element matching the predicate with value. Returns the replaced element.

§Panics

Panics if the object is already in a container.

Source

pub unsafe fn replace_if_raw<F>(&mut self, f: F, value: P) -> Option<P>
where F: FnMut(&P::Target) -> bool,

Replaces the first element matching the predicate with value. Returns the replaced element.

§Panics

Panics if the object is already in a container.

§Safety

The caller must ensure that value is a valid pointer to a T and that the object outlives the reference from the list.

Source

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.

Source

pub fn retain<F>(&mut self, f: F)
where F: FnMut(&P::Target) -> bool,

Retains only the elements specified by the predicate.

Source

pub fn cursor_mut(&mut self) -> CursorMut<'_, P, Tag, S>

Returns a cursor positioned at the front of the list.

Source

pub fn size_slow(&self) -> usize

Calculates the size of the list by iterating through all elements. O(N) time complexity.

Source

pub fn find_if<F>(&self, f: F) -> Option<&P::Target>
where F: FnMut(&P::Target) -> bool,

Finds the first element matching the predicate.

Source

pub fn iter(&self) -> Iterator<'_, P, Tag>

Returns an iterator over the elements of the list.

Source§

impl<P, Tag> SinglyLinkedList<P, Tag, TrackingSize>

Source

pub fn size(&self) -> usize

Returns the size of the list. O(1) time complexity.

Trait Implementations§

Source§

impl<P, Tag, S> Debug for SinglyLinkedList<P, Tag, S>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<P, Tag, S> Drop for SinglyLinkedList<P, Tag, S>

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

fn pin_drop(self: Pin<&mut Self>)

🔬This is a nightly-only experimental API. (pin_ergonomics)
Execute the destructor for this type, but different to Drop::drop, it requires self to be pinned. Read more

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>

§

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>
where S: Unpin, P: Unpin, Tag: Unpin,

§

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> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Init<T> for T

Source§

unsafe fn __init(self, slot: *mut T) -> Result<(), Infallible>

Initializes slot. Read more
Source§

fn chain<F>(self, f: F) -> ChainInit<Self, F, T, E>
where F: FnOnce(&mut T) -> Result<(), E>,

First initializes the value using self then calls the function f with the initialized value. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> PinInit<T> for T

Source§

unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), Infallible>

Initializes slot. Read more
Source§

fn pin_chain<F>(self, f: F) -> ChainPinInit<Self, F, T, E>
where F: FnOnce(Pin<&mut T>) -> Result<(), E>,

First initializes the value using self then calls the function f with the initialized value. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.