### Create a new Builder Source: https://docs.rs/affinitypool/0.4.0/affinitypool/struct.Builder.html Initiates a new `Builder` instance. This is the starting point for configuring a `Threadpool`. ```rust let builder = affinitypool::Builder::new(); ``` -------------------------------- ### Builder::new() Source: https://docs.rs/affinitypool/0.4.0/affinitypool/struct.Builder.html Initiates a new Builder instance to start configuring a Threadpool. ```APIDOC ## Builder::new() ### Description Initiates a new `Builder`. ### Method `pub fn new() -> Builder` ### Examples ```rust let builder = affinitypool::Builder::new(); ``` ``` -------------------------------- ### Example: Managing CPU Affinities with Threads Source: https://docs.rs/affinitypool/0.4.0/src/affinitypool/affinity/mod.rs.html Demonstrates how to retrieve all available CPU core IDs and spawn threads, pinning each to a specific core. This is useful for performance-critical applications requiring fine-grained control over thread execution. ```rust #![allow(unused)] #![allow(non_camel_case_types)] //! This module manages CPU affinities. //! ``` //! use std::thread; //! // Retrieve the IDs of all active CPU cores. //! let core_ids = affinitypool::affinity::get_core_ids().unwrap(); //! // Create a thread for each active CPU core. //! let handles = core_ids.into_iter().map(|id| { //! thread::spawn(move || { //! // Pin this thread to a single CPU core. //! let res = affinitypool::affinity::set_for_current(id); //! if res { //! // Do more work after this. //! } //! }) //! }).collect::>(); //! for handle in handles.into_iter() { //! handle.join().unwrap(); //! } //! ``` mod freebsd; mod linux; mod macos; mod windows; /// This function tries to retrieve information /// on all the "cores" on which the current thread /// is allowed to run. pub fn get_core_ids() -> Option> { get_core_ids_helper() } /// This function tries to pin the current /// thread to the specified core. /// /// # Arguments /// /// * core_id - ID of the core to pin pub fn set_for_current(core_id: CoreId) -> bool { set_for_current_helper(core_id) } /// This represents a CPU core. #[repr(transparent)] #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct CoreId { pub id: usize, } impl From for CoreId { fn from(id: usize) -> CoreId { CoreId { id, } } } // Linux Section #[cfg(any(target_os = "android", target_os = "linux"))] #[inline] fn get_core_ids_helper() -> Option> { linux::get_core_ids() } #[cfg(any(target_os = "android", target_os = "linux"))] #[inline] fn set_for_current_helper(core_id: CoreId) -> bool { linux::set_for_current(core_id) } // Windows Section #[cfg(target_os = "windows")] #[inline] fn get_core_ids_helper() -> Option> { windows::get_core_ids() } #[cfg(target_os = "windows")] #[inline] fn set_for_current_helper(core_id: CoreId) -> bool { windows::set_for_current(core_id) } // MacOS Section #[cfg(target_os = "macos")] #[inline] fn get_core_ids_helper() -> Option> { macos::get_core_ids() } #[cfg(target_os = "macos")] #[inline] fn set_for_current_helper(core_id: CoreId) -> bool { macos::set_for_current(core_id) } // FreeBSD Section #[cfg(target_os = "freebsd")] #[inline] fn get_core_ids_helper() -> Option> { freebsd::get_core_ids() } #[cfg(target_os = "freebsd")] #[inline] fn set_for_current_helper(core_id: CoreId) -> bool { freebsd::set_for_current(core_id) } // Stub Section #[cfg(not(any( target_os = "linux", target_os = "android", target_os = "windows", target_os = "macos", target_os = "freebsd" )))] #[inline] fn get_core_ids_helper() -> Option> { None } #[cfg(not(any( target_os = "linux", target_os = "android", target_os = "windows", target_os = "macos", target_os = "freebsd" )))] #[inline] fn set_for_current_helper(_core_id: CoreId) -> bool { false } ``` -------------------------------- ### Get specified number of threads Source: https://docs.rs/affinitypool/0.4.0/affinitypool/struct.Threadpool.html Returns the number of threads that were specified when the pool was created. This indicates the intended capacity. ```rust pub fn num_threads(&self) -> usize ``` -------------------------------- ### Get Core IDs Source: https://docs.rs/affinitypool/0.4.0/affinitypool/affinity/fn.get_core_ids.html This function tries to retrieve information on all the “cores” on which the current thread is allowed to run. ```rust pub fn get_core_ids() -> Option> ``` -------------------------------- ### Error::description Method (Deprecated) Source: https://docs.rs/affinitypool/0.4.0/affinitypool/enum.Error.html A deprecated method for getting a string description of the error. Prefer using the Display implementation or `to_string()` instead. ```rust fn description(&self) -> &str ``` -------------------------------- ### num_threads Source: https://docs.rs/affinitypool/0.4.0/src/affinitypool/lib.rs.html Get the specified number of threads for this pool. ```APIDOC ## num_threads ### Description Get the specified number of threads for this pool. ### Signature `pub fn num_threads(&self) -> usize` ``` -------------------------------- ### Builder::new Source: https://docs.rs/affinitypool/0.4.0/src/affinitypool/builder.rs.html Initiates a new `Builder` with default settings. ```APIDOC ## Builder::new ### Description Initiates a new [`Builder`] with default settings. ### Method ```rust pub fn new() -> Builder ``` ### Examples ```rust let builder = affinitypool::Builder::new(); ``` ``` -------------------------------- ### Get TypeId of a type Source: https://docs.rs/affinitypool/0.4.0/affinitypool/struct.Threadpool.html Retrieves the unique `TypeId` for a given type. This is part of the Any trait implementation. ```rust fn type_id(&self) -> TypeId ``` -------------------------------- ### spawn Source: https://docs.rs/affinitypool/0.4.0/index.html Queue a new command for execution on the global threadpool. ```APIDOC ## spawn ### Description Queue a new command for execution on the global threadpool. ### Function Signature ```rust fn spawn(future: F) where F: Future + Send + 'static, ``` ``` -------------------------------- ### Builder::build() Source: https://docs.rs/affinitypool/0.4.0/affinitypool/struct.Builder.html Finalizes the configuration and constructs the Threadpool instance. ```APIDOC ## Builder::build() ### Description Finalize the `Builder` and build the `Threadpool`. ### Method `pub fn build(self) -> Threadpool` ### Examples ```rust let pool = affinitypool::Builder::new() .worker_threads(8) .thread_stack_size(4_000_000) .build(); ``` ``` -------------------------------- ### Error::cause Method (Deprecated) Source: https://docs.rs/affinitypool/0.4.0/affinitypool/enum.Error.html A deprecated method for getting the cause of the error. Replaced by `Error::source` which supports downcasting. ```rust fn cause(&self) -> Option<&dyn Error> ``` -------------------------------- ### Sentry::new Source: https://docs.rs/affinitypool/0.4.0/src/affinitypool/sentry.rs.html Creates a new Sentry tracker. It initializes the sentry with its core ID, index, and a weak reference to the shared data. ```APIDOC ## Sentry::new ### Description Creates a new sentry tracker. ### Signature ```rust pub fn new(coreid: Option, index: usize, data: Weak) -> Sentry ``` ### Parameters * `coreid` (Option) - The core ID associated with this sentry. * `index` (usize) - The index of the sentry within its data structure. * `data` (Weak) - A weak reference to the shared data. ### Returns A new `Sentry` instance. ``` -------------------------------- ### spawn Source: https://docs.rs/affinitypool/0.4.0/affinitypool/index.html Queues a new command for execution on the global threadpool. ```APIDOC ## spawn ### Description Queue a new command for execution on the global threadpool. ### Function Signature ```rust pub fn spawn(future: F) where F: Future + Send + 'static, ``` ### Parameters * `future` - The future to be executed on the threadpool. ``` -------------------------------- ### Get CPU Affinity Mask on Linux Source: https://docs.rs/affinitypool/0.4.0/src/affinitypool/affinity/linux.rs.html Retrieves the current CPU affinity mask for the calling thread. Returns None if the operation fails. ```rust #![cfg(any(target_os = "android", target_os = "linux"))] use super::CoreId; use libc::CPU_ISSET; use libc::CPU_SET; use libc::CPU_SETSIZE; use libc::cpu_set_t; use libc::sched_getaffinity; use libc::sched_setaffinity; use std::mem; pub fn get_core_ids() -> Option> { if let Some(full_set) = get_affinity_mask() { let mut core_ids: Vec = Vec::new(); for i in 0..CPU_SETSIZE as usize { if unsafe { CPU_ISSET(i, &full_set) } { core_ids.push(CoreId { id: i, }); } } Some(core_ids) } else { None } } pub fn set_for_current(core_id: CoreId) -> bool { // Turn `core_id` into a `libc::cpu_set_t` with only // one core active. let mut set = new_cpu_set(); unsafe { CPU_SET(core_id.id, &mut set) }; // Set the current thread's core affinity. let res = unsafe { sched_setaffinity( 0, // Defaults to current thread mem::size_of::(), &set, ) }; res == 0 } fn get_affinity_mask() -> Option { let mut set = new_cpu_set(); // Try to get current core affinity mask. let result = unsafe { sched_getaffinity( 0, // Defaults to current thread mem::size_of::(), &mut set, ) }; if result == 0 { Some(set) } else { None } } fn new_cpu_set() -> cpu_set_t { unsafe { mem::zeroed::() } } ``` -------------------------------- ### spawn Source: https://docs.rs/affinitypool/0.4.0/affinitypool Queues a new command for execution on the global thread pool. ```APIDOC ## spawn ### Description Queue a new command for execution on the global threadpool. ### Function Signature ```rust fn spawn(future: F) where F: Future + Send + 'static, ``` ### Parameters * `future`: The future to be executed on the thread pool. ``` -------------------------------- ### Get total number of worker threads Source: https://docs.rs/affinitypool/0.4.0/affinitypool/struct.Threadpool.html Retrieves the total count of worker threads currently active in the pool. This reflects the pool's configured capacity. ```rust pub fn thread_count(&self) -> usize ``` -------------------------------- ### take Source: https://docs.rs/affinitypool/0.4.0/src/affinitypool/atomic_waker.rs.html Returns the last `Waker` passed to `register`, allowing the user to wake it separately. If no waker has been registered, this returns `None`. ```APIDOC ## take ### Description Returns the last `Waker` passed to `register`, so that the user can wake it. This allows for waking the waker separately from the atomic registration process. If a waker has not been registered, this returns `None`. ### Method `pub fn take(&self) -> Option` ``` -------------------------------- ### spawn Source: https://docs.rs/affinitypool/0.4.0/src/affinitypool/lib.rs.html Queues a new command for execution on the global threadpool. If no global threadpool has been created, it runs the closure immediately. ```APIDOC ## spawn(func: F) -> R ### Description Queues a new command for execution on the global threadpool. If no global threadpool has been created, then this function runs the provided closure immediately, without passing it to a blocking threadpool. ### Parameters #### Type Parameters - **F**: FnOnce() -> R + Send + 'static - **R**: Send + 'static ### Returns The result of the executed function. ``` -------------------------------- ### VTable Generation for Generic Types Source: https://docs.rs/affinitypool/0.4.0/src/affinitypool/task.rs.html Implements a mechanism to get the correct `TaskVTable` for any given closure type `F` that implements `FnOnce() + Send`. This uses a trait `HasVTable` to associate the vtable with the type. ```rust fn get_vtable() -> &'static TaskVTable { trait HasVTable { const TABLE: TaskVTable; } impl HasVTable for T { const TABLE: TaskVTable = TaskVTable { call: OwnedTask::call::, drop: OwnedTask::drop::, }; } &::TABLE } ``` -------------------------------- ### AtomicWaker::new Source: https://docs.rs/affinitypool/0.4.0/src/affinitypool/atomic_waker.rs.html Creates a new `AtomicWaker` initialized to the idle state. ```APIDOC ## AtomicWaker::new ### Description Creates a new `AtomicWaker` in an idle state. ### Returns A new `AtomicWaker` instance. ``` -------------------------------- ### spawn Source: https://docs.rs/affinitypool/0.4.0/affinitypool/fn.spawn.html Queues a new command for execution on the global threadpool. If no global threadpool has been created, then this function runs the provided closure immediately, without passing it to a blocking threadpool. ```APIDOC ## spawn ### Description Queue a new command for execution on the global threadpool. If no global threadpool has been created, then this function runs the provided closure immediately, without passing it to a blocking threadpool. ### Signature ```rust pub async fn spawn(func: F) -> R where F: FnOnce() -> R + Send + 'static, R: Send + 'static, ``` ``` -------------------------------- ### Build Threadpool Source: https://docs.rs/affinitypool/0.4.0/affinitypool/struct.Builder.html Finalizes the `Builder` configuration and constructs the `Threadpool` instance. ```rust let pool = affinitypool::Builder::new() .worker_threads(8) .thread_stack_size(4_000_000) .build(); ``` -------------------------------- ### Sentry::new Constructor Source: https://docs.rs/affinitypool/0.4.0/src/affinitypool/sentry.rs.html Creates a new Sentry instance. Initializes the sentry as active and stores the provided core ID, index, and a weak reference to the data. ```rust pub fn new(coreid: Option, index: usize, data: Weak) -> Sentry { Sentry { data, coreid, index, active: true, } } ``` -------------------------------- ### Error::provide Method (Nightly Only) Source: https://docs.rs/affinitypool/0.4.0/affinitypool/enum.Error.html An experimental, nightly-only API for providing type-based access to error context. Use with caution. ```rust fn provide<'a>(&'a self, request: &mut Request<'a>) ``` -------------------------------- ### Manage CPU Affinities with Threads Source: https://docs.rs/affinitypool/0.4.0/affinitypool/affinity/index.html This snippet demonstrates how to retrieve all active CPU core IDs and spawn a thread for each, pinning each thread to its respective core. Ensure the affinitypool crate is included in your project. ```rust use std::thread; // Retrieve the IDs of all active CPU cores. let core_ids = affinitypool::affinity::get_core_ids().unwrap(); // Create a thread for each active CPU core. let handles = core_ids.into_iter().map(|id| { thread::spawn(move || { // Pin this thread to a single CPU core. let res = affinitypool::affinity::set_for_current(id); if res { // Do more work after this. } }) }).collect::>(); for handle in handles.into_iter() { handle.join().unwrap(); } ``` -------------------------------- ### Create a new Threadpool Source: https://docs.rs/affinitypool/0.4.0/affinitypool/struct.Threadpool.html Instantiates a new Threadpool with a specified number of worker threads. Use this to initialize a custom thread pool. ```rust pub fn new(workers: usize) -> Self ``` -------------------------------- ### spawn_local Source: https://docs.rs/affinitypool/0.4.0/affinitypool/fn.spawn_local.html Queues a new command for execution on the global threadpool. The future of this function will block the current thread if it is not fully awaited and driven to completion. If no global threadpool has been created, then this function runs the provided closure immediately, without passing it to a blocking threadpool. ```APIDOC ## spawn_local ### Description Queue a new command for execution on the global threadpool. The future of this function will block the current thread if it is not fully awaited and driven to completion. If no global threadpool has been created, then this function runs the provided closure immediately, without passing it to a blocking threadpool. ### Signature ```rust pub async fn spawn_local<'pool, F, R>(func: F) -> R where F: FnOnce() -> R + Send + 'pool, R: Send + 'pool, ``` ``` -------------------------------- ### Builder::thread_per_core() Source: https://docs.rs/affinitypool/0.4.0/affinitypool/struct.Builder.html Configures the Threadpool to spawn one thread per available CPU core. ```APIDOC ## Builder::thread_per_core() ### Description Set whether a thread should be spawned per core. ### Method `pub fn thread_per_core(self, enabled: bool) -> Builder` ### Examples Each thread spawned will be linked to a separate core: ```rust let pool = affinitypool::Builder::new() .thread_per_core(true) .build(); for _ in 0..10 { pool.spawn(|| { println!("This is executed on individual cores!"); }).await; } ``` ``` -------------------------------- ### Spawn Task on Global Threadpool Source: https://docs.rs/affinitypool/0.4.0/src/affinitypool/lib.rs.html Queues a new command for execution on the global threadpool. If no global threadpool is created, it runs the closure immediately. ```rust pub async fn spawn(func: F) -> R where F: FnOnce() -> R + Send + 'static, R: Send + 'static, { if let Some(threadpool) = THREADPOOL.get() { threadpool.spawn(func).await } else { func() } } ``` -------------------------------- ### Threadpool::spawn Source: https://docs.rs/affinitypool/0.4.0/src/affinitypool/lib.rs.html Queues a new command for execution on this specific thread pool. ```APIDOC ## Threadpool::spawn(&self, func: F) -> R ### Description Queue a new command for execution on this pool. This method encloses the function in an `OwnedTask`, pushes it to the injector, and wakes a parked worker thread if available. ### Parameters #### Type Parameters - **F**: FnOnce() -> R - **R**: Send + 'static - **func** (F): The function to execute. ### Returns The result of the executed function. ``` -------------------------------- ### Threadpool::spawn Source: https://docs.rs/affinitypool/0.4.0/affinitypool/struct.Threadpool.html Queues a new command for execution on the thread pool asynchronously. ```APIDOC ## Threadpool::spawn ### Description Queue a new command for execution on this pool. ### Signature `pub async fn spawn(&self, func: F) -> R` ### Type Parameters * `F`: A closure that takes no arguments and returns a value `R`. Must be `Send` and `'static`. * `R`: The return type of the closure. Must be `Send` and `'static`. ``` -------------------------------- ### spawn_local Source: https://docs.rs/affinitypool/0.4.0/index.html Queue a new command for execution on the global threadpool. The future of this function will block the current thread if it is not fully awaited and driven to completion. ```APIDOC ## spawn_local ### Description Queue a new command for execution on the global threadpool. The future of this function will block the current thread if it is not fully awaited and driven to completion. ### Function Signature ```rust fn spawn_local(future: F) where F: Future + 'static, ``` ``` -------------------------------- ### spawn_local Source: https://docs.rs/affinitypool/0.4.0/affinitypool Queues a new command for execution on the global thread pool, with specific behavior for blocking futures. ```APIDOC ## spawn_local ### Description Queue a new command for execution on the global threadpool. The future of this function will block the current thread if it is not fully awaited and driven to completion. ### Function Signature ```rust fn spawn_local(future: F) where F: Future + 'static, ``` ### Parameters * `future`: The future to be executed on the thread pool. This future will block the current thread if not fully awaited. ``` -------------------------------- ### Initialize Global Threadpool Source: https://docs.rs/affinitypool/0.4.0/src/affinitypool/global.rs.html Initializes the global thread pool using `OnceLock`. This ensures the thread pool is created only once and lazily. ```rust use crate::Threadpool; use std::sync::OnceLock; pub(crate) static THREADPOOL: OnceLock = OnceLock::new(); ``` -------------------------------- ### CoreId Implementations Source: https://docs.rs/affinitypool/0.4.0/affinitypool/affinity/struct.CoreId.html Details the various trait implementations for the CoreId struct, including Clone, Debug, From, Hash, Ord, PartialEq, PartialOrd, Copy, Eq, and others. ```APIDOC ### impl Clone for CoreId * `fn clone(&self) -> CoreId` - Returns a duplicate of the value. * `fn clone_from(&mut self, source: &Self)` - Performs copy-assignment from `source`. ### impl Debug for CoreId * `fn fmt(&self, f: &mut Formatter<'_>) -> Result` - Formats the value using the given formatter. ### impl From for CoreId * `fn from(id: usize) -> CoreId` - Converts to this type from the input type. ### impl Hash for CoreId * `fn hash<__H: Hasher>(&self, state: &mut __H)` - Feeds this value into the given `Hasher`. * `fn hash_slice(data: &[Self], state: &mut H)` - Feeds a slice of this type into the given `Hasher`. ### impl Ord for CoreId * `fn cmp(&self, other: &CoreId) -> Ordering` - Returns an `Ordering` between `self` and `other`. * `fn max(self, other: Self) -> Self` - Compares and returns the maximum of two values. * `fn min(self, other: Self) -> Self` - Compares and returns the minimum of two values. * `fn clamp(self, min: Self, max: Self) -> Self` - Restrict a value to a certain interval. ### impl PartialEq for CoreId * `fn eq(&self, other: &CoreId) -> bool` - Tests for `self` and `other` values to be equal. * `fn ne(&self, other: &Rhs) -> bool` - Tests for `!=`. ### impl PartialOrd for CoreId * `fn partial_cmp(&self, other: &CoreId) -> Option` - Returns an ordering between `self` and `other` values if one exists. * `fn lt(&self, other: &Rhs) -> bool` - Tests less than. * `fn le(&self, other: &Rhs) -> bool` - Tests less than or equal to. * `fn gt(&self, other: &Rhs) -> bool` - Tests greater than. * `fn ge(&self, other: &Rhs) -> bool` - Tests greater than or equal to. ### impl Copy for CoreId ### impl Eq for CoreId ### impl StructuralPartialEq for CoreId ``` -------------------------------- ### spawn_local Source: https://docs.rs/affinitypool/0.4.0/affinitypool/index.html Queues a new command for execution on the global threadpool. The future of this function will block the current thread if it is not fully awaited and driven to completion. ```APIDOC ## spawn_local ### Description Queue a new command for execution on the global threadpool. The future of this function will block the current thread if it is not fully awaited and driven to completion. ### Function Signature ```rust pub fn spawn_local(future: F) where F: Future + 'static, ``` ### Parameters * `future` - The future to be executed on the threadpool. ``` -------------------------------- ### Build AffinityPool Threadpool Source: https://docs.rs/affinitypool/0.4.0/src/affinitypool/builder.rs.html Constructs and initializes an AffinityPool threadpool. It sets up shared data, including thread names, stack sizes, and synchronization primitives. Threads are spawned based on the `thread_per_core` configuration. ```rust let data = Arc::new(Data { name: self.thread_name, stack_size: self.thread_stack_size, num_threads: AtomicUsize::new(threads), thread_count: AtomicUsize::new(0), injector, stealers: RwLock::new(stealers), shutdown: AtomicBool::new(false), parked_threads: ArrayQueue::new(threads), thread_handles: RwLock::new(Vec::new()), }); // Use affinity if spawning thread per core if self.thread_per_core { // Spawn the desired number of workers for (id, worker) in workers.into_iter().enumerate() { Threadpool::spin_up(Some(id), data.clone(), worker, id); } } else { // Spawn the desired number of workers for (index, worker) in workers.into_iter().enumerate() { Threadpool::spin_up(None, data.clone(), worker, index); } } // Return the new threadpool Threadpool { data, } } } ``` -------------------------------- ### Threadpool::spawn_local Source: https://docs.rs/affinitypool/0.4.0/affinitypool/struct.Threadpool.html Queues a new command for execution on the thread pool with access to local variables. ```APIDOC ## Threadpool::spawn_local ### Description Queue a new command for execution on this pool with access to the local variables. The future of this function will block the current thread if it is not fully completed. ### Signature `pub fn spawn_local<'pool, F, R>( &'pool self, func: F, ) -> SpawnFuture<'pool, F, R>` ### Type Parameters * `'pool`: The lifetime of the thread pool. * `F`: A closure that takes no arguments and returns a value `R`. Must be `Send` and `'pool`. * `R`: The return type of the closure. Must be `Send` and `'pool`. ``` -------------------------------- ### Creating a New OwnedTask Source: https://docs.rs/affinitypool/0.4.0/src/affinitypool/task.rs.html The `new` function constructs an `OwnedTask` from a closure `f`. It allocates memory for `TaskData`, initializes it with the closure and the appropriate vtable, and returns a new `OwnedTask`. ```rust pub fn new(f: F) -> Self { let b = Box::new(TaskData { table: Self::get_vtable::(), data: ManuallyDrop::new(f), }); // Safety: a box can never have a null pointer inside it. Self(unsafe { NonNull::new_unchecked(Box::into_raw(b).cast()) }, PhantomData) } ``` -------------------------------- ### spawn_local Source: https://docs.rs/affinitypool/0.4.0/src/affinitypool/lib.rs.html Queues a new command for execution on the global threadpool, allowing access to local variables. The future of this function will block the current thread if not fully awaited. ```APIDOC ## spawn_local<'pool, F, R>(func: F) -> R ### Description Queues a new command for execution on the global threadpool. The future of this function will block the current thread if it is not fully awaited and driven to completion. If no global threadpool has been created, then this function runs the provided closure immediately, without passing it to a blocking threadpool. ### Parameters #### Type Parameters - **'pool**: Lifetime parameter for the pool. - **F**: FnOnce() -> R - **R**: Send + 'pool ### Returns The result of the executed function. ``` -------------------------------- ### From for CoreId Conversion Source: https://docs.rs/affinitypool/0.4.0/affinitypool/affinity/struct.CoreId.html Allows creating a CoreId instance directly from a usize value. This is useful for initializing a CoreId when the core's numerical identifier is known. ```rust impl From for CoreId { fn from(id: usize) -> CoreId; } ``` -------------------------------- ### Initialize pointer Source: https://docs.rs/affinitypool/0.4.0/affinitypool/struct.Threadpool.html Initializes a value at the given pointer address. This is an unsafe operation and part of the Pointable trait. ```rust unsafe fn init(init: ::Init) -> usize ``` -------------------------------- ### Spawn an async task on the Threadpool Source: https://docs.rs/affinitypool/0.4.0/affinitypool/struct.Threadpool.html Queues a new asynchronous command for execution on the thread pool. The task and its result must be Send and have a 'static lifetime. ```rust pub async fn spawn(&self, func: F) -> R where F: FnOnce() -> R + Send + 'static, R: Send + 'static, ``` -------------------------------- ### Spawn Local Task on Threadpool Source: https://docs.rs/affinitypool/0.4.0/src/affinitypool/lib.rs.html Queues a new command for execution on this pool, providing access to local variables. The future returned will block the current thread if not fully completed. ```rust pub fn spawn_local<'pool, F, R>(&'pool self, func: F) -> SpawnFuture<'pool, F, R> where F: FnOnce() -> R, F: Send + 'pool, R: Send + 'pool, { SpawnFuture::new(self, func) } ``` -------------------------------- ### CoreId PartialEq Implementation Source: https://docs.rs/affinitypool/0.4.0/affinitypool/affinity/struct.CoreId.html Defines equality comparison for CoreId instances. This allows checking if two CoreId values represent the same CPU core. ```rust impl PartialEq for CoreId { fn eq(&self, other: &CoreId) -> bool; fn ne(&self, other: &Rhs) -> bool; } ``` -------------------------------- ### Spawn a local task on the Threadpool Source: https://docs.rs/affinitypool/0.4.0/affinitypool/struct.Threadpool.html Queues a new command for execution on the thread pool, allowing access to local variables. The returned future will block the current thread if not completed. ```rust pub fn spawn_local<'pool, F, R>( &'pool self, func: F, ) -> SpawnFuture<'pool, F, R> where F: FnOnce() -> R + Send + 'pool, R: Send + 'pool, ``` -------------------------------- ### CoreId Debug Implementation Source: https://docs.rs/affinitypool/0.4.0/affinitypool/affinity/struct.CoreId.html Provides a way to format CoreId instances for debugging purposes. This allows CoreId values to be printed in a human-readable format. ```rust impl Debug for CoreId { fn fmt(&self, f: &mut Formatter<'_>) -> Result; } ``` -------------------------------- ### SpawnFuture Implementation Source: https://docs.rs/affinitypool/0.4.0/src/affinitypool/local.rs.html The `SpawnFuture` struct enables spawning a closure onto a threadpool and awaiting its result. It manages the task's lifecycle from initialization to completion, handling potential panics during execution. ```rust use std::{ any::Any, future::Future, panic::{self, AssertUnwindSafe}, pin::Pin, sync::{Arc, Condvar, Mutex}, task::{Context, Poll}, }; use crate::{Threadpool, atomic_waker::AtomicWaker, task::OwnedTask}; struct SpawnFutureData { // cond var to wait on the result of the mutex changing when we find it empty during block. condvar: Condvar, // Waker to notify the runtime of completion of the task. waker: AtomicWaker, // The actual value, if the future is properly driven to completion we never block on the mutex. result: Mutex>>>, } enum State { Init(F), Running(Arc>), Done, } /// A future that spawns a task on the threadpool and returns the result. #[must_use = "futures do nothing unless you `.await` or poll them"] pub struct SpawnFuture<'pool, F, R> { pool: &'pool Threadpool, state: State, } unsafe impl Send for SpawnFutureData {} unsafe impl Sync for SpawnFutureData {} impl<'pool, F, R> SpawnFuture<'pool, F, R> where F: FnOnce() -> R + Send, R: Send, { pub(crate) fn new(pool: &'pool Threadpool, f: F) -> Self { SpawnFuture { pool, state: State::Init(f), } } } impl Future for SpawnFuture<'_, F, T> where F: FnOnce() -> T + Send, T: Send, { type Output = T; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { // Pin is structural for everything, and is maintained by the function impl. loop { // Safety: We're maintaining pinning guarantees throughout let this = unsafe { self.as_mut().get_unchecked_mut() }; // Match on the current state of the future. match this.state { State::Init(_) => { // Transition to a Done state before we submit the task to avoid race conditions. let State::Init(task) = std::mem::replace(&mut this.state, State::Done) else { unreachable!() }; // Create the data for the future. let data = Arc::new(SpawnFutureData { condvar: Condvar::new(), result: Mutex::new(None), waker: AtomicWaker::new(), }); // Register waker before submitting task to avoid race condition. data.waker.register(cx.waker()); // Clone the data for the future. let data_clone = data.clone(); // Create the task to run the passed function. let task = OwnedTask::new(move || { // Execute task and store result. { // Store the result of the task in the mutex. let mut lock = data_clone.result.lock().unwrap(); // Run the task itself, and catch any panics. let res = panic::catch_unwind(AssertUnwindSafe(task)); // Store the result in the mutex. *lock = Some(res); // Lock drops here automatically. } // Wake the future. data_clone.waker.wake(); // Notify any blocked threads. data_clone.condvar.notify_one(); }); // Safety: task lifetime is erased but we maintain it via Arc unsafe { // Push the task to the global injector. this.pool.data.injector.push(task.erase_lifetime()); } // Wake up a parked worker thread. if let Some(thread) = this.pool.data.parked_threads.pop() { thread.unpark(); } // Transition this future to the Running state. this.state = State::Running(data); } State::Running(ref data) => { // Clone the Arc so we can work with it without borrowing from state let data = data.clone(); // Try to get the result match data.result.try_lock() { Ok(mut guard) => { if let Some(res) = guard.take() { // Result is ready, drop the guard first drop(guard); // Now we can modify state this.state = State::Done; return Poll::Ready( res.unwrap_or_else(|p| panic::resume_unwind(p)), ); } else { // Task not complete yet drop(guard); data.waker.register(cx.waker()); return Poll::Pending; } } Err(_) => { // Task is currently writing result data.waker.register(cx.waker()); return Poll::Pending; } } } State::Done => { // We should never get to this state by polling a future once done. panic!("SpawnFuture polled after completion") } } } } } impl Drop for SpawnFuture<'_, F, T> { fn drop(&mut self) { if let State::Running(ref data) = self.state { // Block and wait for completion let guard = data.result.lock().unwrap(); // Wait until result is ready (handling spurious wakeups) ``` -------------------------------- ### spawn_local Function Signature Source: https://docs.rs/affinitypool/0.4.0/affinitypool/fn.spawn_local.html This is the function signature for `spawn_local`. It queues a closure for execution on the global threadpool. The future returned will block the current thread if not fully awaited. If no global threadpool exists, the closure runs immediately. ```rust pub async fn spawn_local<'pool, F, R>(func: F) -> R where F: FnOnce() -> R + Send + 'pool, R: Send + 'pool, ``` -------------------------------- ### AtomicWaker state transitions Source: https://docs.rs/affinitypool/0.4.0/src/affinitypool/atomic_waker.rs.html Handles state transitions for concurrent wake operations, including REGISTERING, WAKING, and WAITING states. Ensures proper memory ordering and synchronization. ```rust // concurrent thread called `wake`. In this // case, `actual` **must** be `REGISTERING | // `WAKING`. debug_assert_eq!(actual, REGISTERING | WAKING); // Take the waker to wake once the atomic operation has // completed. let waker = (*self.waker.get()).take().unwrap(); // We need to return to WAITING state (clear our lock and // concurrent WAKING flag). This needs to acquire all // WAKING fetch_or releases and it needs to release our // update to self.waker, so we need a `swap` operation. self.state.swap(WAITING, AcqRel); // memory ordering: we acquired the state for all // concurrent wakes, but future wakes might still // need to wake us in case we can't make progress // from the pending wakes. // // So we simply schedule to come back later (we could // also simply leave the registration in place above). waker.wake(); } } } } WAKING => { // Currently in the process of waking the task, i.e., // `wake` is currently being called on the old task handle. // // memory ordering: we acquired the state for all // concurrent wakes, but future wakes might still // need to wake us in case we can't make progress // from the pending wakes. // // So we simply schedule to come back later ( // could also spin here trying to acquire the lock // to register). waker.wake_by_ref(); } state => { // In this case, a concurrent thread is holding the // "registering" lock. This probably indicates a bug in the // caller's code as racing to call `register` doesn't make much // sense. // // memory ordering: don't care. a concurrent register() is going // to succeed and provide proper memory ordering. // // We just want to maintain memory safety. It is ok to drop the // call to `register`. debug_assert!(state == REGISTERING || state == REGISTERING | WAKING); } } } ``` -------------------------------- ### Sentry Drop Implementation Source: https://docs.rs/affinitypool/0.4.0/src/affinitypool/sentry.rs.html Handles the cleanup and potential thread respawning when a Sentry is dropped. If the Sentry was active when dropped, it indicates a panic, and a new thread is spawned. ```APIDOC ## Sentry Drop ### Description Implements the `Drop` trait for `Sentry`. When a `Sentry` is dropped, this logic checks if it was still active. If it was active, it implies that the associated task panicked without properly cancelling the sentry. In such cases, a new thread is spawned to replace the one that panicked. ### Behavior 1. Attempts to upgrade the weak reference to the `Data`. 2. If the `Sentry` is `active`: a. Creates a new `Worker`. b. Updates the `stealers` in `data` with the new worker's stealer. c. Spawns a new thread using `Threadpool::spin_up`. ``` -------------------------------- ### Spawn Task on Threadpool Source: https://docs.rs/affinitypool/0.4.0/src/affinitypool/lib.rs.html Queues a new command for execution on this specific thread pool. It uses a oneshot channel to return the result and handles panics by resuming the unwind. ```rust pub async fn spawn(&self, func: F) -> R where F: FnOnce() -> R, F: Send + 'static, R: Send + 'static, { // Create a new oneshot channel let (tx, rx) = oneshot::channel(); // Enclose the function in a closure let task = OwnedTask::new(move || { tx.send(catch_unwind(AssertUnwindSafe(func))).ok(); }); // Push the task to the global injector self.data.injector.push(task); // Wake up a parked worker thread if let Some(thread) = self.data.parked_threads.pop() { thread.unpark(); } // The channel has not been closed let res = rx.await.unwrap(); // Wait for the function response res.unwrap_or_else(|err| resume_unwind(err)) } ``` -------------------------------- ### TryInto for CoreId Source: https://docs.rs/affinitypool/0.4.0/affinitypool/affinity/struct.CoreId.html Implementation of the `TryInto` trait for `CoreId`. This enables attempting to convert a `CoreId` into another type `U`, returning a `Result`. ```APIDOC ## impl TryInto for T ### Description Provides a mechanism to attempt conversion from a type to another, with error handling. ### Associated Types - `Error`: The type returned in the event of a conversion error. This is determined by the `TryFrom` implementation for the target type `U`. ``` ```APIDOC ### fn try_into(self) -> Result>::Error> #### Description Performs the conversion from the current type `T` (e.g., `CoreId`) to type `U`. #### Returns A `Result` containing the converted value of type `U` on success, or an error on failure. ``` -------------------------------- ### wake Source: https://docs.rs/affinitypool/0.4.0/src/affinitypool/atomic_waker.rs.html Calls `wake` on the last `Waker` passed to `register`. If `register` has not been called yet, this operation does nothing. ```APIDOC ## wake ### Description Calls `wake` on the last `Waker` passed to `register`. If `register` has not been called yet, this operation does nothing. ### Method `pub fn wake(&self)` ``` -------------------------------- ### AtomicWaker::take() Source: https://docs.rs/affinitypool/0.4.0/src/affinitypool/atomic_waker.rs.html Returns the last `Waker` passed to `register`, allowing the user to wake it separately. If a waker has not been registered, this returns `None`. AcqRel ordering is used to acquire the value of the `task` cell and establish a `release` ordering with associated memory. ```rust /// Returns the last `Waker` passed to `register`, so that the user can wake it. /// /// /// Sometimes, just waking the AtomicWaker is not fine grained enough. This allows the user /// to take the waker and then wake it separately, rather than performing both steps in one /// atomic action. /// /// If a waker has not been registered, this returns `None`. pub fn take(&self) -> Option { // AcqRel ordering is used in order to acquire the value of the `task` // cell as well as to establish a `release` ordering with whatever // memory the `AtomicWaker` is associated with. match self.state.fetch_or(WAKING, AcqRel) { WAITING => { // The waking lock has been acquired. let waker = unsafe { (*self.waker.get()).take() }; // Release the lock self.state.fetch_and(!WAKING, Release); waker } state => { // There is a concurrent thread currently updating the // associated task. // // Nothing more to do as the `WAKING` bit has been set. It // doesn't matter if there are concurrent registering threads or // not. // debug_assert!( state == REGISTERING || state == REGISTERING | WAKING || state == WAKING ); None } } } ``` -------------------------------- ### CoreId PartialOrd Implementation Source: https://docs.rs/affinitypool/0.4.0/affinitypool/affinity/struct.CoreId.html Provides partial ordering comparisons for CoreId instances. This is used for operators like <, <=, >, and >=. ```rust impl PartialOrd for CoreId { fn partial_cmp(&self, other: &CoreId) -> Option; fn lt(&self, other: &Rhs) -> bool; fn le(&self, other: &Rhs) -> bool; fn gt(&self, other: &Rhs) -> bool; fn ge(&self, other: &Rhs) -> bool; } ``` -------------------------------- ### Spawn Local Task on Global Threadpool Source: https://docs.rs/affinitypool/0.4.0/src/affinitypool/lib.rs.html Queues a new command for execution on the global threadpool, allowing access to local variables. The future blocks the current thread if not fully awaited. If no global threadpool exists, it runs the closure immediately. ```rust pub async fn spawn_local<'pool, F, R>(func: F) -> R where F: FnOnce() -> R, F: Send + 'pool, R: Send + 'pool, { if let Some(threadpool) = THREADPOOL.get() { threadpool.spawn_local(func).await } else { func() } } ``` -------------------------------- ### Build Global Threadpool Source: https://docs.rs/affinitypool/0.4.0/src/affinitypool/lib.rs.html Sets this thread pool as the global thread pool. Returns an error if a global thread pool already exists. ```rust pub fn build_global(self) -> Result<(), Error> { // Check if the threadpool has been created if THREADPOOL.get().is_some() { return Err(Error::GlobalThreadpoolExists); } // Set this threadpool as the global threadpool THREADPOOL.get_or_init(|| self); // Global threadpool was created successfully Ok(()) } ``` -------------------------------- ### CoreId StructuralPartialEq Implementation Source: https://docs.rs/affinitypool/0.4.0/affinitypool/affinity/struct.CoreId.html Implements structural equality comparison for CoreId. This is often used in generic contexts where structural equality is required. ```rust impl StructuralPartialEq for CoreId {} ``` -------------------------------- ### Generic Blanket Implementations for CoreId Source: https://docs.rs/affinitypool/0.4.0/affinitypool/affinity/struct.CoreId.html Shows blanket implementations of common traits like Any, Borrow, BorrowMut, CloneToUninit, From, Into, Pointable, and ToOwned for CoreId. These provide general functionality based on the struct's properties. ```rust impl Any for T where T: 'static + ?Sized {} impl Borrow for T where T: ?Sized {} impl BorrowMut for T where T: ?Sized {} impl CloneToUninit for T where T: Clone {} impl Into for T where U: From {} impl Pointable for T {} impl ToOwned for T where T: Clone {} ``` -------------------------------- ### CoreId Clone Implementation Source: https://docs.rs/affinitypool/0.4.0/affinitypool/affinity/struct.CoreId.html Enables creating a duplicate of a CoreId instance. This is a standard implementation for types that can be copied. ```rust impl Clone for CoreId { fn clone(&self) -> CoreId; } ```