Struct PidAllocator

Source
pub struct PidAllocator<const ORDER: usize> { /* private fields */ }
Expand description

A thread-safe PID allocator that can allocate and recycle PIDs efficiently. It encapsulates the allocator’s state within an Arc<SpinMutex<...>> to allow safe shared access across threads. This design ensures that PIDs can be allocated and recycled from multiple threads without data races or consistency issues.

The ORDER generic parameter determines the capacity of the allocator, with the total number of allocatable PIDs being ORDER * usize::BITS. This makes the allocator flexible for various use cases, whether you need a few dozen PIDs or thousands.

§Examples

Creating a new PID Allocator:

use pid_allocator::PidAllocator;

let allocator = PidAllocator::<8>::new(); // Creates an allocator that can manage up to 8 * usize::BITS PIDs.

//Allocating a PID:
if let Some(pid) = allocator.allocate() {
    println!("Successfully allocated PID: {}", *pid);
    // When the `pid` goes out of scope, it will be automatically recycled.
} else {
    println!("Failed to allocate a PID. The allocator might be full.");
}

//Checking if a PID is allocated (using `contains` method):
let pid = allocator.allocate().expect("Failed to allocate PID");
assert!(allocator.contains(*pid), "The PID should be marked as allocated.");
 
//Recycle a PID by simply dropping it:
{
    let pid = allocator.allocate().expect("Failed to allocate PID");
    // PID is in use within this scope
}
// PID is automatically recycled here when `pid` goes out of scope

§Note

This allocator is designed to be used in environments where PID recycling is frequent, and thread safety is a concern. Its performance characteristics are optimized for scenarios where both allocation and deallocation (recycling) of PIDs are common operations.

Implementations§

Source§

impl<const ORDER: usize> PidAllocator<ORDER>

Source

pub fn new() -> Self

Creates a new instance of the PID allocator.

This constructor initializes the PID allocator, setting up its internal structure to keep track of allocated and available PIDs. The allocator supports up to ORDER * usize::BITS unique PIDs, where ORDER is a compile-time constant defining the number of layers in the allocator.

§Examples
use pid_allocator::PidAllocator;

let allocator = PidAllocator::<8>::new();

This creates a PID allocator with 8 layers, capable of managing a total of 8 * usize::BITS PIDs, which depends on the architecture (e.g., 256 PIDs for a 32-bit architecture or 512 PIDs for a 64-bit architecture).

Source

pub fn allocate(&self) -> Option<Pid<ORDER>>

Attempts to allocate a new PID. Returns Some(Pid) if successful, or None if all PIDs are currently allocated. The allocated PID is wrapped in a Pid object, which will automatically recycle the PID when dropped.

This method locks the internal state, searches for a free PID, marks it as used, and returns a Pid instance representing the allocated PID. If no PIDs are available, it returns None.

§Returns
  • Some(Pid<ORDER>) containing the allocated PID if allocation is successful.
  • None if all PIDs are already allocated.
§Examples

Successful allocation:

use pid_allocator::PidAllocator;

let allocator = PidAllocator::<8>::new();
if let Some(pid) = allocator.allocate() {
    println!("Allocated PID: {}", *pid);
}

Handling failure to allocate a PID:

use pid_allocator::PidAllocator;

let allocator = PidAllocator::<8>::new();
let mut pids = Vec::new();
while let Some(pid) = allocator.allocate() {
    pids.push(pid);
}
// At this point, no more PIDs can be allocated.
assert!(allocator.allocate().is_none());

In this example, PIDs are continuously allocated until no more are available, at which point allocate() returns None.

Source

pub fn contains(&self, number: usize) -> bool

Checks whether a given PID is currently allocated.

§Parameters
  • number: The PID number to check for allocation.
§Returns
  • true if the PID is currently allocated.
  • false otherwise.
§Example
use pid_allocator::PidAllocator;

let allocator = PidAllocator::<32>::new();
let pid = allocator.allocate().expect("Failed to allocate PID");

assert!(allocator.contains(*pid), "The PID should be marked as allocated.");
§Note

This method performs a read-only operation on the allocator’s state and is thread-safe, thanks to the internal use of Arc<SpinMutex<...>>. However, because the state of the allocator can change in concurrent environments, the returned allocation state might not remain valid immediately after this method is called.

Trait Implementations§

Source§

impl<const ORDER: usize> Debug for PidAllocator<ORDER>

Source§

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

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

impl<const ORDER: usize> Default for PidAllocator<ORDER>

Source§

fn default() -> PidAllocator<ORDER>

Returns the “default value” for a type. Read more

Auto Trait Implementations§

§

impl<const ORDER: usize> Freeze for PidAllocator<ORDER>

§

impl<const ORDER: usize> !RefUnwindSafe for PidAllocator<ORDER>

§

impl<const ORDER: usize> Send for PidAllocator<ORDER>

§

impl<const ORDER: usize> Sync for PidAllocator<ORDER>

§

impl<const ORDER: usize> Unpin for PidAllocator<ORDER>

§

impl<const ORDER: usize> !UnwindSafe for PidAllocator<ORDER>

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, 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, 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.