Skip to main content

CleanupGroup

Struct CleanupGroup 

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

An owned thread-pool cleanup group.

Create members with CleanupGroup::create_work, CleanupGroup::create_timer, CleanupGroup::create_periodic_timer, and CleanupGroup::create_wait, then release them all with CleanupGroup::close_members. Drop releases any members that are still open, so forgetting to call close_members is safe – it only gives up control over when the teardown blocks.

§Examples

use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::time::Duration;
use windows_threadpool_sys::cleanup_group::CleanupGroup;

let count = Arc::new(AtomicUsize::new(0));
let work_counter = Arc::clone(&count);
let timer_counter = Arc::clone(&count);

let mut group = CleanupGroup::new()?;
{
    let work = group.create_work(move || {
        work_counter.fetch_add(1, Ordering::SeqCst);
    }, None)?;
    let timer = group.create_timer(move |_firing| {
        timer_counter.fetch_add(1, Ordering::SeqCst);
    }, None)?;

    work.submit();
    timer.set_after(Duration::from_millis(1));

    // Wait for the work to have run and the timer to have fired. Note that
    // `timer.wait()` would not do: it waits for callbacks the pool has
    // already queued, and a timer that has not expired yet has none.
    while count.load(Ordering::SeqCst) < 2 {
        std::thread::yield_now();
    }
}

// One call tears down every member of the group.
group.close_members();
assert_eq!(count.load(Ordering::SeqCst), 2);

Implementations§

Source§

impl CleanupGroup

Source

pub fn new() -> Result<Self>

Create an empty cleanup group.

§Errors

Returns the error from CreateThreadpoolCleanupGroup.

Source

pub fn create_work<F>( &self, callback: F, env: Option<&CallbackEnviron<'_>>, ) -> Result<WorkMember<'_>>
where F: Fn() + Send + Sync + 'static,

Create a work object owned by this group.

Equivalent to ThreadpoolWork::new, except that the returned member is released by CleanupGroup::close_members rather than by its own drop.

§Errors

Returns the error from CreateThreadpoolWork.

Source

pub fn create_timer<F>( &self, callback: F, env: Option<&CallbackEnviron<'_>>, ) -> Result<TimerMember<'_>>
where F: Fn(&TimerFiring<'_>) + Send + Sync + 'static,

Create a one-shot timer owned by this group.

Equivalent to ThreadpoolTimer::new.

§Errors

Returns the error from CreateThreadpoolTimer.

Source

pub fn create_periodic_timer<F>( &self, period: Duration, callback: F, env: Option<&CallbackEnviron<'_>>, ) -> Result<PeriodicTimerMember<'_>>
where F: Fn(&PeriodicTick<'_>) + Send + Sync + 'static,

Create a periodic timer owned by this group.

Equivalent to ThreadpoolPeriodicTimer::new, including that its ticks may overlap one another.

§Errors

Returns io::ErrorKind::InvalidInput if period is outside ThreadpoolPeriodicTimer::MIN_PERIOD..=ThreadpoolPeriodicTimer::MAX_PERIOD or is not a whole number of milliseconds, or the error from CreateThreadpoolTimer.

Source

pub fn create_wait<F>( &self, handle: WaitableHandle, callback: F, env: Option<&CallbackEnviron<'_>>, ) -> Result<WaitMember<'_>>
where F: Fn(&WaitActivation<'_>) + Send + Sync + 'static,

Create a wait object owned by this group, watching handle.

The group takes ownership of the handle as well as the object, because the pool may still be watching it until the members are released.

Like ThreadpoolWait::new, this takes a WaitableHandle rather than a bare handle, so the group path cannot reach the unsupported wait targets that the individually-owned path rejects.

§Errors

Returns the error from CreateThreadpoolWait.

Source

pub fn close_members(&mut self)

Release every member of this group, letting queued callbacks run.

Waits for executing callbacks to finish; callbacks that have not started run before the release completes.

Taking &mut self is what makes members unusable afterwards: they borrow the group, so the compiler rejects any later use of one. Calling this twice is harmless – the second call finds no members.

The group remains usable afterwards. New members may be created on it, and they are released by the next call or by Drop, exactly as the first batch was.

To drop queued callbacks instead of running them, see close_members_cancelling – named without a link because it does not exist in a build with self-heal off, while this method does, so a link would dangle in that configuration.

Source

pub fn close_members_cancelling(&mut self)

Release every member of this group, dropping queued callbacks.

As close_members, except that callbacks which have not started are dropped rather than run.

A cancelling release passes the cancel through to every member, so a wait among them reaches the same removal primitive ThreadpoolWait::try_cancel_pending does, and owes its pool the same repair. This crate marks that repair here, which is what makes this safe to offer – subject to the same stated hole as the per-object method: a member whose pool could not be registered for repair has that registration retried during this call, and only if the retry also fails is it cancelled with nothing to repair it, recording cancel-untracked and panicking under fail-fast.

§Availability

Requires the self-heal feature, which is on by default. Without it this method does not exist and a call to it fails to compile, naming close_members_cancelling_no_heal_tracking as what to reach for instead. That is the designed behaviour, not an oversight: the repair this method performs is what the feature provides, and a compile error is the only way a caller relying on it finds out it is gone.

Source

pub unsafe fn close_members_cancelling_no_heal_tracking(&mut self)

close_members_cancelling without the repair.

Not a link, deliberately: the method it would name does not exist in a build with self-heal off, and this one does, so the link would dangle in exactly the configuration this method exists for.

Always present, including in builds with self-heal off, which is the point: it is the method that still exists when the gated one does not, and its signature says what the caller takes on.

§Safety

The caller must ensure every member’s pool is repaired. Submitting any work item to a pool does so; so does knowing it is kept live by something else. Leaving one unrepaired can stop that pool dispatching – which, for the process-default pool, reaches every component in the process, including code with no connection to this call.

This is not a memory-safety obligation, and the keyword is not claiming one. It is here because the obligation is statable and dischargeable by the caller, which is what unsafe marks; see the self-heal decision.

Source

pub fn owned_resources(&self) -> usize

The number of contexts and handles the group is holding for its members.

Zero once the members have been released.

Trait Implementations§

Source§

impl Debug for CleanupGroup

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Drop for CleanupGroup

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

fn pin_drop(self: Pin<&mut Self>)

🔬This is a nightly-only experimental API. (pin_ergonomics)
Execute the destructor for this type, but different to Drop::drop, it requires self to be pinned. Read more
Source§

impl Send for CleanupGroup

Source§

impl Sync for CleanupGroup

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 = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

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.