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
impl LocalManager
Sourcepub fn current_epoch(&self) -> usize
pub fn current_epoch(&self) -> usize
Returns the current epoch.
Returns a reference to the associated SharedManager.
Sourcepub unsafe fn schedule_deallocate<T>(&mut self, ptr: *const T)
pub unsafe fn schedule_deallocate<T>(&mut self, ptr: *const T)
Sourcepub unsafe fn schedule_deallocate_slice<T>(&mut self, ptr: *const T, len: usize)
pub unsafe fn schedule_deallocate_slice<T>(&mut self, ptr: *const T, len: usize)
Sourcepub unsafe fn schedule_drop<F: FnOnce()>(&mut self, func: F)
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.
Sourcepub fn maybe_pass_epoch(&mut self, now: OrengineInstant)
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.
Sourcepub unsafe fn deregister()
pub unsafe fn deregister()
Deregisters the thread-local LocalManager.
After that the calling local_manager can cause undefined behavior before the next
registration.
§Safety
- The thread must be registered in the
SharedManager. - It is called only once for one
registration. - After calling this function, the caller doesn’t call
local_managerbefore the nextregistration.
§Panics
It the thread is not registered.