LocalManager

Struct LocalManager 

Source
pub struct LocalManager { /* private fields */ }
Expand description

A local manager of objects that need to be deallocated or dropped when it is safe.

It should be created by some runtime with SharedManager::register_new_executor, and only the runtime can call LocalManager::deregister and LocalManager::maybe_pass_epoch. The runtime should call LocalManager::deregister when it is stopped and should call LocalManager::maybe_pass_epoch periodically (it uses cached time to prevent unnecessary attempts to pass the epoch).

After the registration, the LocalManager is stored in thread-local storage and can be accessed with local_manager.

It allows scheduling objects to be deallocated or dropped when it is safe.

Use LocalManager::schedule_deallocate and LocalManager::schedule_deallocate_slice to schedule deallocation of objects, and LocalManager::schedule_drop to schedule dropping of objects.

§Example

use std::cell::Cell;
use light_qsbr::{local_manager, SharedManager, orengine_utils::instant::OrengineInstant, LocalManager};

fn start_runtime() {
    let mut runtime = Runtime { tasks: Vec::new(), is_stopped: Cell::new(false) };
    let shared_manager = SharedManager::new();

    shared_manager.register_new_executor();

    'runtime: loop {
        for _ in 0..61 {
            if let Some(task) = runtime.tasks.pop() {
                task();
            } else {
                break 'runtime;
            }
        }

        if runtime.is_stopped.get() {
            break;
        }

        local_manager().maybe_pass_epoch(OrengineInstant::now()); // Free some memory if it is safe
    }

    unsafe { LocalManager::deregister() };
}

fn one_of_tasks(lock_free_stack: LockFreeStack<usize>) {
    let node = lock_free_stack.pop();
    let ptr_to_deallocate: *mut LockFreeStackNode<usize> = node.get_node_ptr();
    // It's not safe to release the node right now because other threads can load it but still not read it.
    unsafe {
        local_manager() // Get the thread-local LocalManager
            .schedule_deallocate(ptr_to_deallocate);
    }
    // The node will be deallocated when it is safe.
}

Implementations§

Source§

impl LocalManager

Source

pub fn current_epoch(&self) -> usize

Returns the current epoch.

Source

pub fn shared_manager(&self) -> &SharedManager

Returns a reference to the associated SharedManager.

Source

pub unsafe fn schedule_deallocate<T>(&mut self, ptr: *const T)

Schedules deallocation of an object. It will be deallocated when it is safe.

§Safety

It requires the same safety conditions as dealloc.

Source

pub unsafe fn schedule_deallocate_slice<T>(&mut self, ptr: *const T, len: usize)

Schedules deallocation of the provided slice. They will be deallocated when it is safe.

§Safety

It requires the same safety conditions as dealloc.

§Panics
Source

pub unsafe fn schedule_drop<F: FnOnce()>(&mut self, func: F)

Schedules dropping of the provided function. It will be dropped when it is safe.

The function can be a closure; therefore, it can be used to drop any object.

§Safety

It requires the same safety conditions as mem::ManuallyDrop::drop.

Source

pub fn maybe_pass_epoch(&mut self, now: OrengineInstant)

Maybe passes the epoch and frees some memory if it is safe.

This function accepts the current time as a parameter to avoid very often epoch passing.

While at least one thread doesn’t pass the epoch, all other threads can’t free memory.

Source

pub unsafe fn deregister()

Deregisters the thread-local LocalManager. After that the calling local_manager can cause undefined behavior before the next registration.

§Safety
§Panics

It the thread is not registered.

Auto Trait Implementations§

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.