Skip to content

Commit

Permalink
Move Status to the util module.
Browse files Browse the repository at this point in the history
  • Loading branch information
gendx committed Sep 20, 2024
1 parent 9a3b40c commit 32ff906
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 54 deletions.
56 changes: 2 additions & 54 deletions src/thread_pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use super::range::{
};
use crate::macros::{log_debug, log_error, log_warn};
// Platforms that support `libc::sched_setaffinity()`.
use super::util::SliceView;
use super::util::{SliceView, Status};
#[cfg(all(
not(miri),
any(
Expand All @@ -30,7 +30,7 @@ use nix::{
use std::cell::Cell;
use std::num::NonZeroUsize;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::{Arc, Condvar, Mutex, MutexGuard, PoisonError, RwLock};
use std::sync::{Arc, Mutex, RwLock};
use std::thread::{Scope, ScopedJoinHandle};

/// A builder for [`ThreadPool`].
Expand Down Expand Up @@ -138,58 +138,6 @@ impl RoundColor {
}
}

/// An ergonomic wrapper around a [`Mutex`]-[`Condvar`] pair.
struct Status<T> {
mutex: Mutex<T>,
condvar: Condvar,
}

impl<T> Status<T> {
/// Creates a new status initialized with the given value.
fn new(t: T) -> Self {
Self {
mutex: Mutex::new(t),
condvar: Condvar::new(),
}
}

/// Attempts to set the status to the given value and notifies one waiting
/// thread.
///
/// Fails if the [`Mutex`] is poisoned.
fn try_notify_one(&self, t: T) -> Result<(), PoisonError<MutexGuard<'_, T>>> {
*self.mutex.lock()? = t;
self.condvar.notify_one();
Ok(())
}

/// If the predicate is true on this status, sets the status to the given
/// value and notifies one waiting thread.
fn notify_one_if(&self, predicate: impl Fn(&T) -> bool, t: T) {
let mut locked = self.mutex.lock().unwrap();
if predicate(&*locked) {
*locked = t;
self.condvar.notify_one();
}
}

/// Sets the status to the given value and notifies all waiting threads.
fn notify_all(&self, t: T) {
*self.mutex.lock().unwrap() = t;
self.condvar.notify_all();
}

/// Waits until the predicate is true on this status.
///
/// This returns a [`MutexGuard`], allowing to further inspect or modify the
/// status.
fn wait_while(&self, predicate: impl FnMut(&mut T) -> bool) -> MutexGuard<T> {
self.condvar
.wait_while(self.mutex.lock().unwrap(), predicate)
.unwrap()
}
}

/// A thread pool tied to a scope, that can process inputs into outputs of the
/// given types.
pub struct ThreadPool<'scope, Input, Output> {
Expand Down
54 changes: 54 additions & 0 deletions src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,60 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::sync::{Condvar, Mutex, MutexGuard, PoisonError};

/// An ergonomic wrapper around a [`Mutex`]-[`Condvar`] pair.
pub struct Status<T> {
mutex: Mutex<T>,
condvar: Condvar,
}

impl<T> Status<T> {
/// Creates a new status initialized with the given value.
pub fn new(t: T) -> Self {
Self {
mutex: Mutex::new(t),
condvar: Condvar::new(),
}
}

/// Attempts to set the status to the given value and notifies one waiting
/// thread.
///
/// Fails if the [`Mutex`] is poisoned.
pub fn try_notify_one(&self, t: T) -> Result<(), PoisonError<MutexGuard<'_, T>>> {
*self.mutex.lock()? = t;
self.condvar.notify_one();
Ok(())
}

/// If the predicate is true on this status, sets the status to the given
/// value and notifies one waiting thread.
pub fn notify_one_if(&self, predicate: impl Fn(&T) -> bool, t: T) {
let mut locked = self.mutex.lock().unwrap();
if predicate(&*locked) {
*locked = t;
self.condvar.notify_one();
}
}

/// Sets the status to the given value and notifies all waiting threads.
pub fn notify_all(&self, t: T) {
*self.mutex.lock().unwrap() = t;
self.condvar.notify_all();
}

/// Waits until the predicate is true on this status.
///
/// This returns a [`MutexGuard`], allowing to further inspect or modify the
/// status.
pub fn wait_while(&self, predicate: impl FnMut(&mut T) -> bool) -> MutexGuard<T> {
self.condvar
.wait_while(self.mutex.lock().unwrap(), predicate)
.unwrap()
}
}

/// A lifetime-erased slice. This acts as a [`&[T]`](slice) but whose lifetime
/// can be adjusted via the `unsafe` function [`get()`](Self::get).
pub struct SliceView<T> {
Expand Down

0 comments on commit 32ff906

Please sign in to comment.