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
impl CleanupGroup
Sourcepub fn create_work<F>(
&self,
callback: F,
env: Option<&CallbackEnviron<'_>>,
) -> Result<WorkMember<'_>>
pub fn create_work<F>( &self, callback: F, env: Option<&CallbackEnviron<'_>>, ) -> Result<WorkMember<'_>>
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.
Sourcepub fn create_timer<F>(
&self,
callback: F,
env: Option<&CallbackEnviron<'_>>,
) -> Result<TimerMember<'_>>
pub fn create_timer<F>( &self, callback: F, env: Option<&CallbackEnviron<'_>>, ) -> Result<TimerMember<'_>>
Create a one-shot timer owned by this group.
Equivalent to ThreadpoolTimer::new.
§Errors
Returns the error from CreateThreadpoolTimer.
Sourcepub fn create_periodic_timer<F>(
&self,
period: Duration,
callback: F,
env: Option<&CallbackEnviron<'_>>,
) -> Result<PeriodicTimerMember<'_>>
pub fn create_periodic_timer<F>( &self, period: Duration, callback: F, env: Option<&CallbackEnviron<'_>>, ) -> Result<PeriodicTimerMember<'_>>
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.
Sourcepub fn create_wait<F>(
&self,
handle: WaitableHandle,
callback: F,
env: Option<&CallbackEnviron<'_>>,
) -> Result<WaitMember<'_>>
pub fn create_wait<F>( &self, handle: WaitableHandle, callback: F, env: Option<&CallbackEnviron<'_>>, ) -> Result<WaitMember<'_>>
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.
Sourcepub fn close_members(&mut self)
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.
Sourcepub fn close_members_cancelling(&mut self)
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.
Sourcepub unsafe fn close_members_cancelling_no_heal_tracking(&mut self)
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.
Sourcepub fn owned_resources(&self) -> usize
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.