forked from ROMEO/nexosim
Restrict visibility of many items to super
This commit is contained in:
parent
b009f4481e
commit
abab030b4a
@ -9,10 +9,10 @@ use super::{GlobalQueue, Stealer};
|
|||||||
|
|
||||||
/// A view of the thread pool shared between the executor and all workers.
|
/// A view of the thread pool shared between the executor and all workers.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct Pool {
|
pub(super) struct Pool {
|
||||||
pub(crate) global_queue: GlobalQueue,
|
pub(super) global_queue: GlobalQueue,
|
||||||
pub(crate) executor_id: usize,
|
pub(super) executor_id: usize,
|
||||||
pub(crate) executor_unparker: parking::Unparker,
|
pub(super) executor_unparker: parking::Unparker,
|
||||||
registry: PoolRegistry,
|
registry: PoolRegistry,
|
||||||
stealers: Box<[Stealer]>,
|
stealers: Box<[Stealer]>,
|
||||||
worker_unparkers: Box<[parking::Unparker]>,
|
worker_unparkers: Box<[parking::Unparker]>,
|
||||||
@ -23,7 +23,7 @@ pub(crate) struct Pool {
|
|||||||
|
|
||||||
impl Pool {
|
impl Pool {
|
||||||
/// Creates a new pool.
|
/// Creates a new pool.
|
||||||
pub(crate) fn new(
|
pub(super) fn new(
|
||||||
executor_id: usize,
|
executor_id: usize,
|
||||||
executor_unparker: parking::Unparker,
|
executor_unparker: parking::Unparker,
|
||||||
shared_data: impl Iterator<Item = (Stealer, parking::Unparker)>,
|
shared_data: impl Iterator<Item = (Stealer, parking::Unparker)>,
|
||||||
@ -47,14 +47,14 @@ impl Pool {
|
|||||||
/// Marks all pool workers as active.
|
/// Marks all pool workers as active.
|
||||||
///
|
///
|
||||||
/// Unparking the worker threads is the responsibility of the caller.
|
/// Unparking the worker threads is the responsibility of the caller.
|
||||||
pub(crate) fn set_all_workers_active(&self) {
|
pub(super) fn set_all_workers_active(&self) {
|
||||||
self.registry.set_all_active();
|
self.registry.set_all_active();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Marks all pool workers as inactive.
|
/// Marks all pool workers as inactive.
|
||||||
///
|
///
|
||||||
/// Unparking the executor threads is the responsibility of the caller.
|
/// Unparking the executor threads is the responsibility of the caller.
|
||||||
pub(crate) fn set_all_workers_inactive(&self) {
|
pub(super) fn set_all_workers_inactive(&self) {
|
||||||
self.registry.set_all_inactive();
|
self.registry.set_all_inactive();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,7 +66,7 @@ impl Pool {
|
|||||||
/// If this was the last active worker, `false` is returned and it is
|
/// If this was the last active worker, `false` is returned and it is
|
||||||
/// guaranteed that all memory operations performed by threads that called
|
/// guaranteed that all memory operations performed by threads that called
|
||||||
/// `activate_worker` will be visible.
|
/// `activate_worker` will be visible.
|
||||||
pub(crate) fn try_set_worker_inactive(&self, worker_id: usize) -> bool {
|
pub(super) fn try_set_worker_inactive(&self, worker_id: usize) -> bool {
|
||||||
self.registry.try_set_inactive(worker_id)
|
self.registry.try_set_inactive(worker_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,7 +78,7 @@ impl Pool {
|
|||||||
/// idle state without observing the tasks scheduled by this caller. If this
|
/// idle state without observing the tasks scheduled by this caller. If this
|
||||||
/// is not tolerable (for instance if this method is called from a
|
/// is not tolerable (for instance if this method is called from a
|
||||||
/// non-worker thread), use the more expensive `activate_worker`.
|
/// non-worker thread), use the more expensive `activate_worker`.
|
||||||
pub(crate) fn activate_worker_relaxed(&self) {
|
pub(super) fn activate_worker_relaxed(&self) {
|
||||||
if let Some(worker_id) = self.registry.set_one_active_relaxed() {
|
if let Some(worker_id) = self.registry.set_one_active_relaxed() {
|
||||||
self.searching_workers.fetch_add(1, Ordering::Relaxed);
|
self.searching_workers.fetch_add(1, Ordering::Relaxed);
|
||||||
self.worker_unparkers[worker_id].unpark();
|
self.worker_unparkers[worker_id].unpark();
|
||||||
@ -88,7 +88,7 @@ impl Pool {
|
|||||||
/// Unparks an idle worker if any is found and mark it as active, or ensure
|
/// Unparks an idle worker if any is found and mark it as active, or ensure
|
||||||
/// that at least the last active worker will observe all memory operations
|
/// that at least the last active worker will observe all memory operations
|
||||||
/// performed before this call when calling `try_set_worker_inactive`.
|
/// performed before this call when calling `try_set_worker_inactive`.
|
||||||
pub(crate) fn activate_worker(&self) {
|
pub(super) fn activate_worker(&self) {
|
||||||
if let Some(worker_id) = self.registry.set_one_active() {
|
if let Some(worker_id) = self.registry.set_one_active() {
|
||||||
self.searching_workers.fetch_add(1, Ordering::Relaxed);
|
self.searching_workers.fetch_add(1, Ordering::Relaxed);
|
||||||
self.worker_unparkers[worker_id].unpark();
|
self.worker_unparkers[worker_id].unpark();
|
||||||
@ -99,28 +99,28 @@ impl Pool {
|
|||||||
///
|
///
|
||||||
/// If `true` is returned, it is guaranteed that all operations performed by
|
/// If `true` is returned, it is guaranteed that all operations performed by
|
||||||
/// the now-inactive workers become visible in this thread.
|
/// the now-inactive workers become visible in this thread.
|
||||||
pub(crate) fn is_pool_idle(&self) -> bool {
|
pub(super) fn is_pool_idle(&self) -> bool {
|
||||||
self.registry.is_idle()
|
self.registry.is_idle()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Increments the count of workers actively searching for tasks.
|
/// Increments the count of workers actively searching for tasks.
|
||||||
pub(crate) fn begin_worker_search(&self) {
|
pub(super) fn begin_worker_search(&self) {
|
||||||
self.searching_workers.fetch_add(1, Ordering::Relaxed);
|
self.searching_workers.fetch_add(1, Ordering::Relaxed);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Decrements the count of workers actively searching for tasks.
|
/// Decrements the count of workers actively searching for tasks.
|
||||||
pub(crate) fn end_worker_search(&self) {
|
pub(super) fn end_worker_search(&self) {
|
||||||
self.searching_workers.fetch_sub(1, Ordering::Relaxed);
|
self.searching_workers.fetch_sub(1, Ordering::Relaxed);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the count of workers actively searching for tasks.
|
/// Returns the count of workers actively searching for tasks.
|
||||||
pub(crate) fn searching_worker_count(&self) -> usize {
|
pub(super) fn searching_worker_count(&self) -> usize {
|
||||||
self.searching_workers.load(Ordering::Relaxed)
|
self.searching_workers.load(Ordering::Relaxed)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Triggers the termination signal and unparks all worker threads so they
|
/// Triggers the termination signal and unparks all worker threads so they
|
||||||
/// can cleanly terminate.
|
/// can cleanly terminate.
|
||||||
pub(crate) fn trigger_termination(&self) {
|
pub(super) fn trigger_termination(&self) {
|
||||||
self.terminate_signal.store(true, Ordering::Relaxed);
|
self.terminate_signal.store(true, Ordering::Relaxed);
|
||||||
|
|
||||||
self.registry.set_all_active();
|
self.registry.set_all_active();
|
||||||
@ -130,7 +130,7 @@ impl Pool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if the termination signal was triggered.
|
/// Returns true if the termination signal was triggered.
|
||||||
pub(crate) fn termination_is_triggered(&self) -> bool {
|
pub(super) fn termination_is_triggered(&self) -> bool {
|
||||||
self.terminate_signal.load(Ordering::Relaxed)
|
self.terminate_signal.load(Ordering::Relaxed)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,7 +139,7 @@ impl Pool {
|
|||||||
/// If no panic is currently registered, the panic in argument is
|
/// If no panic is currently registered, the panic in argument is
|
||||||
/// registered. If a panic was already registered by a worker and was not
|
/// registered. If a panic was already registered by a worker and was not
|
||||||
/// yet processed by the executor, then nothing is done.
|
/// yet processed by the executor, then nothing is done.
|
||||||
pub(crate) fn register_panic(&self, panic: Box<dyn Any + Send + 'static>) {
|
pub(super) fn register_panic(&self, panic: Box<dyn Any + Send + 'static>) {
|
||||||
let mut worker_panic = self.worker_panic.lock().unwrap();
|
let mut worker_panic = self.worker_panic.lock().unwrap();
|
||||||
if worker_panic.is_none() {
|
if worker_panic.is_none() {
|
||||||
*worker_panic = Some(panic);
|
*worker_panic = Some(panic);
|
||||||
@ -147,7 +147,7 @@ impl Pool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Takes a worker panic if any is registered.
|
/// Takes a worker panic if any is registered.
|
||||||
pub(crate) fn take_panic(&self) -> Option<Box<dyn Any + Send + 'static>> {
|
pub(super) fn take_panic(&self) -> Option<Box<dyn Any + Send + 'static>> {
|
||||||
let mut worker_panic = self.worker_panic.lock().unwrap();
|
let mut worker_panic = self.worker_panic.lock().unwrap();
|
||||||
worker_panic.take()
|
worker_panic.take()
|
||||||
}
|
}
|
||||||
@ -156,7 +156,7 @@ impl Pool {
|
|||||||
/// workers, starting from a randomly selected active worker. The worker
|
/// workers, starting from a randomly selected active worker. The worker
|
||||||
/// which ID is provided in argument (if any) is excluded from the pool of
|
/// which ID is provided in argument (if any) is excluded from the pool of
|
||||||
/// candidates.
|
/// candidates.
|
||||||
pub(crate) fn shuffled_stealers<'a>(
|
pub(super) fn shuffled_stealers<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
excluded_worker_id: Option<usize>,
|
excluded_worker_id: Option<usize>,
|
||||||
rng: &'_ rng::Rng,
|
rng: &'_ rng::Rng,
|
||||||
@ -173,7 +173,7 @@ impl Pool {
|
|||||||
|
|
||||||
/// An iterator over active workers that yields their associated stealer,
|
/// An iterator over active workers that yields their associated stealer,
|
||||||
/// starting from a randomly selected worker.
|
/// starting from a randomly selected worker.
|
||||||
pub(crate) struct ShuffledStealers<'a> {
|
pub(super) struct ShuffledStealers<'a> {
|
||||||
stealers: &'a [Stealer],
|
stealers: &'a [Stealer],
|
||||||
// A bit-rotated bit field of the remaining candidate workers to steal from.
|
// A bit-rotated bit field of the remaining candidate workers to steal from.
|
||||||
// If set, the LSB represents the next candidate.
|
// If set, the LSB represents the next candidate.
|
||||||
|
@ -12,7 +12,7 @@ use crate::loom_exports::cell::UnsafeCell;
|
|||||||
use crate::loom_exports::sync::atomic::{AtomicU32, AtomicU64};
|
use crate::loom_exports::sync::atomic::{AtomicU32, AtomicU64};
|
||||||
use crate::loom_exports::{debug_or_loom_assert, debug_or_loom_assert_eq};
|
use crate::loom_exports::{debug_or_loom_assert, debug_or_loom_assert_eq};
|
||||||
|
|
||||||
pub(crate) use buffers::*;
|
pub(super) use buffers::*;
|
||||||
|
|
||||||
mod buffers;
|
mod buffers;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -180,13 +180,13 @@ impl<T, B: Buffer<T>> Drop for Queue<T, B> {
|
|||||||
|
|
||||||
/// Handle for single-threaded FIFO push and pop operations.
|
/// Handle for single-threaded FIFO push and pop operations.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct Worker<T, B: Buffer<T>> {
|
pub(super) struct Worker<T, B: Buffer<T>> {
|
||||||
queue: Arc<Queue<T, B>>,
|
queue: Arc<Queue<T, B>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, B: Buffer<T>> Worker<T, B> {
|
impl<T, B: Buffer<T>> Worker<T, B> {
|
||||||
/// Creates a new queue and returns a `Worker` handle.
|
/// Creates a new queue and returns a `Worker` handle.
|
||||||
pub(crate) fn new() -> Self {
|
pub(super) fn new() -> Self {
|
||||||
let queue = Arc::new(Queue {
|
let queue = Arc::new(Queue {
|
||||||
heads: CachePadded::new(AtomicU64::new(0)),
|
heads: CachePadded::new(AtomicU64::new(0)),
|
||||||
tail: CachePadded::new(AtomicU32::new(0)),
|
tail: CachePadded::new(AtomicU32::new(0)),
|
||||||
@ -201,7 +201,7 @@ impl<T, B: Buffer<T>> Worker<T, B> {
|
|||||||
///
|
///
|
||||||
/// An arbitrary number of `Stealer` handles can be created, either using
|
/// An arbitrary number of `Stealer` handles can be created, either using
|
||||||
/// this method or cloning an existing `Stealer` handle.
|
/// this method or cloning an existing `Stealer` handle.
|
||||||
pub(crate) fn stealer(&self) -> Stealer<T, B> {
|
pub(super) fn stealer(&self) -> Stealer<T, B> {
|
||||||
Stealer {
|
Stealer {
|
||||||
queue: self.queue.clone(),
|
queue: self.queue.clone(),
|
||||||
}
|
}
|
||||||
@ -212,7 +212,7 @@ impl<T, B: Buffer<T>> Worker<T, B> {
|
|||||||
///
|
///
|
||||||
/// Note that that the spare capacity may be underestimated due to
|
/// Note that that the spare capacity may be underestimated due to
|
||||||
/// concurrent stealing operations.
|
/// concurrent stealing operations.
|
||||||
pub(crate) fn spare_capacity(&self) -> usize {
|
pub(super) fn spare_capacity(&self) -> usize {
|
||||||
let capacity = <B as Buffer<T>>::CAPACITY;
|
let capacity = <B as Buffer<T>>::CAPACITY;
|
||||||
let stealer_head = unpack_heads(self.queue.heads.load(Relaxed)).1;
|
let stealer_head = unpack_heads(self.queue.heads.load(Relaxed)).1;
|
||||||
let tail = self.queue.tail.load(Relaxed);
|
let tail = self.queue.tail.load(Relaxed);
|
||||||
@ -230,7 +230,7 @@ impl<T, B: Buffer<T>> Worker<T, B> {
|
|||||||
///
|
///
|
||||||
/// This will fail if the queue is full, in which case the item is returned
|
/// This will fail if the queue is full, in which case the item is returned
|
||||||
/// as the error field.
|
/// as the error field.
|
||||||
pub(crate) fn push(&self, item: T) -> Result<(), T> {
|
pub(super) fn push(&self, item: T) -> Result<(), T> {
|
||||||
let stealer_head = unpack_heads(self.queue.heads.load(Acquire)).1;
|
let stealer_head = unpack_heads(self.queue.heads.load(Acquire)).1;
|
||||||
let tail = self.queue.tail.load(Relaxed);
|
let tail = self.queue.tail.load(Relaxed);
|
||||||
|
|
||||||
@ -258,7 +258,7 @@ impl<T, B: Buffer<T>> Worker<T, B> {
|
|||||||
/// spare capacity to accommodate all iterator items, for instance by
|
/// spare capacity to accommodate all iterator items, for instance by
|
||||||
/// calling `[Worker::spare_capacity]` beforehand. Otherwise, the iterator
|
/// calling `[Worker::spare_capacity]` beforehand. Otherwise, the iterator
|
||||||
/// is dropped while still holding the items in excess.
|
/// is dropped while still holding the items in excess.
|
||||||
pub(crate) fn extend<I: IntoIterator<Item = T>>(&self, iter: I) {
|
pub(super) fn extend<I: IntoIterator<Item = T>>(&self, iter: I) {
|
||||||
let stealer_head = unpack_heads(self.queue.heads.load(Acquire)).1;
|
let stealer_head = unpack_heads(self.queue.heads.load(Acquire)).1;
|
||||||
let mut tail = self.queue.tail.load(Relaxed);
|
let mut tail = self.queue.tail.load(Relaxed);
|
||||||
|
|
||||||
@ -284,7 +284,7 @@ impl<T, B: Buffer<T>> Worker<T, B> {
|
|||||||
/// Attempts to pop one item from the head of the queue.
|
/// Attempts to pop one item from the head of the queue.
|
||||||
///
|
///
|
||||||
/// This returns None if the queue is empty.
|
/// This returns None if the queue is empty.
|
||||||
pub(crate) fn pop(&self) -> Option<T> {
|
pub(super) fn pop(&self) -> Option<T> {
|
||||||
let mut heads = self.queue.heads.load(Acquire);
|
let mut heads = self.queue.heads.load(Acquire);
|
||||||
|
|
||||||
let prev_worker_head = loop {
|
let prev_worker_head = loop {
|
||||||
@ -343,7 +343,7 @@ impl<T, B: Buffer<T>> Worker<T, B> {
|
|||||||
/// An error is returned in the following cases:
|
/// An error is returned in the following cases:
|
||||||
/// 1) no item was stolen, either because the queue is empty or `N` is 0,
|
/// 1) no item was stolen, either because the queue is empty or `N` is 0,
|
||||||
/// 2) a concurrent stealing operation is ongoing.
|
/// 2) a concurrent stealing operation is ongoing.
|
||||||
pub(crate) fn drain<C>(&self, count_fn: C) -> Result<Drain<'_, T, B>, StealError>
|
pub(super) fn drain<C>(&self, count_fn: C) -> Result<Drain<'_, T, B>, StealError>
|
||||||
where
|
where
|
||||||
C: FnMut(usize) -> usize,
|
C: FnMut(usize) -> usize,
|
||||||
{
|
{
|
||||||
@ -373,7 +373,7 @@ unsafe impl<T: Send, B: Buffer<T>> Send for Worker<T, B> {}
|
|||||||
/// This iterator is created by [`Worker::drain`]. See its documentation for
|
/// This iterator is created by [`Worker::drain`]. See its documentation for
|
||||||
/// more.
|
/// more.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct Drain<'a, T, B: Buffer<T>> {
|
pub(super) struct Drain<'a, T, B: Buffer<T>> {
|
||||||
queue: &'a Queue<T, B>,
|
queue: &'a Queue<T, B>,
|
||||||
head: u32,
|
head: u32,
|
||||||
from_head: u32,
|
from_head: u32,
|
||||||
@ -448,7 +448,7 @@ unsafe impl<'a, T: Send, B: Buffer<T>> Sync for Drain<'a, T, B> {}
|
|||||||
|
|
||||||
/// Handle for multi-threaded stealing operations.
|
/// Handle for multi-threaded stealing operations.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct Stealer<T, B: Buffer<T>> {
|
pub(super) struct Stealer<T, B: Buffer<T>> {
|
||||||
queue: Arc<Queue<T, B>>,
|
queue: Arc<Queue<T, B>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -474,7 +474,7 @@ impl<T, B: Buffer<T>> Stealer<T, B> {
|
|||||||
/// an error as long as one element could be returned directly. This can
|
/// an error as long as one element could be returned directly. This can
|
||||||
/// occur if the destination queue is full, if the source queue has only one
|
/// occur if the destination queue is full, if the source queue has only one
|
||||||
/// item or if `N` is 1.
|
/// item or if `N` is 1.
|
||||||
pub(crate) fn steal_and_pop<C, BDest>(
|
pub(super) fn steal_and_pop<C, BDest>(
|
||||||
&self,
|
&self,
|
||||||
dest: &Worker<T, BDest>,
|
dest: &Worker<T, BDest>,
|
||||||
count_fn: C,
|
count_fn: C,
|
||||||
@ -557,7 +557,7 @@ unsafe impl<T: Send, B: Buffer<T>> Sync for Stealer<T, B> {}
|
|||||||
|
|
||||||
/// Error returned when stealing is unsuccessful.
|
/// Error returned when stealing is unsuccessful.
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub(crate) enum StealError {
|
pub(super) enum StealError {
|
||||||
/// No item was stolen.
|
/// No item was stolen.
|
||||||
Empty,
|
Empty,
|
||||||
/// Another concurrent stealing operation is ongoing.
|
/// Another concurrent stealing operation is ongoing.
|
||||||
|
@ -8,14 +8,14 @@ use super::LocalQueue;
|
|||||||
|
|
||||||
/// A local worker with access to global executor resources.
|
/// A local worker with access to global executor resources.
|
||||||
pub(crate) struct Worker {
|
pub(crate) struct Worker {
|
||||||
pub(crate) local_queue: LocalQueue,
|
pub(super) local_queue: LocalQueue,
|
||||||
pub(crate) fast_slot: Cell<Option<Runnable>>,
|
pub(super) fast_slot: Cell<Option<Runnable>>,
|
||||||
pub(crate) pool: Arc<Pool>,
|
pub(super) pool: Arc<Pool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Worker {
|
impl Worker {
|
||||||
/// Creates a new worker.
|
/// Creates a new worker.
|
||||||
pub(crate) fn new(local_queue: LocalQueue, pool: Arc<Pool>) -> Self {
|
pub(super) fn new(local_queue: LocalQueue, pool: Arc<Pool>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
local_queue,
|
local_queue,
|
||||||
fast_slot: Cell::new(None),
|
fast_slot: Cell::new(None),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user