usesuper::*; use core::{marker::PhantomData, ops::Deref};
/// A `Pool` object represents a private thread pool with its own thread limits. /// /// This is in contrast to the default, or shared, thread pool used by the crate's `submit` function /// as well as other code within the same process. pubstruct Pool(Box<TP_CALLBACK_ENVIRON_V3>);
impl Pool { /// Creates a new `Pool` object. pubfn new() -> Self { letmut e = TP_CALLBACK_ENVIRON_V3 {
Version: 3,
CallbackPriority: TP_CALLBACK_PRIORITY_NORMAL,
Size: core::mem::size_of::<TP_CALLBACK_ENVIRON_V3>() as u32,
..Default::default()
};
// The `TP_CALLBACK_ENVIRON_V3` is boxed to ensure its memory address remains stable for the life of the `Pool` object. Self(Box::new(e))
}
/// Convenience function for creating a new pool and calling [`scope`][Self::scope]. pubfn with_scope<'env, F>(f: F) where
F: for<'scope> FnOnce(&'scope Scope<'scope, 'env>),
{ let pool = Pool::new();
pool.scope(f);
}
/// Sets the thread limits for the `Pool` object. pubfn set_thread_limits(&self, min: u32, max: u32) { unsafe {
check(SetThreadpoolThreadMinimum(self.0.Pool, min));
SetThreadpoolThreadMaximum(self.0.Pool, max);
}
}
/// Submit the closure to the thread pool. /// /// * The closure must have `'static` lifetime as the thread may outlive the lifetime in which `submit` is called. /// * The closure must be `Send` as it will be sent to another thread for execution. pubfn submit<F: FnOnce() + Send + 'static>(&self, f: F) { // This is safe because the closure has a `'static` lifetime. unsafe {
try_submit(&*self.0, f);
}
}
/// Create a scope for submitting closures. /// /// Within this scope local variables can be sent to the pool thread for execution. /// This is possible because `scope` will wait for all submitted closures to finish before returning, /// Note however that it will also wait for closures that were submitted from other threads. pubfn scope<'env, F>(&self, f: F) where
F: for<'scope> FnOnce(&'scope Scope<'scope, 'env>),
{ struct DropGuard<'a>(&'a Pool); impl Drop for DropGuard<'_> { fn drop(&mutself) { self.0.join();
}
} // Ensure that we always join the pool before returning. let _guard = DropGuard(self); let scope = Scope {
pool: self,
env: PhantomData,
scope: PhantomData,
};
f(&scope);
}
/// Waits for all submissions to finish. /// /// Dropping the `Pool` will also wait for all submissions to finish. pubfn join(&self) { unsafe {
CloseThreadpoolCleanupGroupMembers(self.0.CleanupGroup, 0, core::ptr::null_mut());
}
}
}
impl Default for Pool { fn default() -> Self { Self::new()
}
}
unsafeimpl Sync for Pool {} unsafeimpl Send for Pool {}
impl Drop for Pool { fn drop(&mutself) { // The `Pool` object cannot be dropped without waiting for all closures to complete, as their // lifetimes are only guaranteed to be as long as the `Pool` object. self.join();
/// A scope to submit closures in. /// /// See [`scope`][Pool::scope] for details. pubstruct Scope<'scope, 'env: 'scope> {
pool: &'scope Pool,
scope: PhantomData<&'scope mut &'scope ()>,
env: PhantomData<&'env mut &'env ()>,
}
impl<'scope, 'env> Scope<'scope, 'env> { /// Submits the closure to run on the `Pool`. /// /// The closure cannot outlive the `Scope` it's run in. pubfn submit<F: FnOnce() + Send + 'scope>(&'scope self, f: F) { unsafe {
try_submit(&*self.pool.0, f);
}
}
}
impl Deref for Scope<'_, '_> { type Target = Pool; fn deref(&self) -> &Self::Target { self.pool
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.