Struct Pool
struct Pool<T, F = fn() -> T>(_)
A thread safe pool that works in an alloc-only context.
Getting a value out comes with a guard. When that guard is dropped, the
value is automatically put back in the pool. The guard provides both a
Deref and a DerefMut implementation for easy access to an underlying
T.
A Pool impls Sync when T is Send (even if T is not Sync). This
is possible because a pool is guaranteed to provide a value to exactly one
thread at any time.
Currently, a pool never contracts in size. Its size is proportional to the maximum number of simultaneous uses. This may change in the future.
A Pool is a particularly useful data structure for this crate because
many of the regex engines require a mutable "cache" in order to execute
a search. Since regexes themselves tend to be global, the problem is then:
how do you get a mutable cache to execute a search? You could:
- Use a
thread_local!, which requires the standard library and requires that the regex pattern be statically known. - Use a
Pool. - Make the cache an explicit dependency in your code and pass it around.
- Put the cache state in a
Mutex, but this means only one search can execute at a time. - Create a new cache for every search.
A thread_local! is perhaps the best choice if it works for your use case.
Putting the cache in a mutex or creating a new cache for every search are
perhaps the worst choices. Of the remaining two choices, whether you use
this Pool or thread through a cache explicitly in your code is a matter
of taste and depends on your code architecture.
Warning: may use a spin lock
When this crate is compiled without the std feature, then this type
may used a spin lock internally. This can have subtle effects that may
be undesirable. See Spinlocks Considered Harmful for a more
thorough treatment of this topic.
Example
This example shows how to share a single hybrid regex among multiple
threads, while also safely getting exclusive access to a hybrid's
Cache without preventing other searches
from running while your thread uses the Cache.
use ;
static RE: =
new;
static CACHE: =
new;
let expected = Some;
assert_eq!;
Implementations
impl<T, F> Pool<T, F>
fn new(create: F) -> Pool<T, F>Create a new pool. The given closure is used to create values in the pool when necessary.
impl<T: Send, F: Fn() -> T> Pool<T, F>
fn get(self: &Self) -> PoolGuard<'_, T, F>Get a value from the pool. The caller is guaranteed to have exclusive access to the given value. Namely, it is guaranteed that this will never return a value that was returned by another call to
getbut was not put back into the pool.When the guard goes out of scope and its destructor is called, then it will automatically be put back into the pool. Alternatively,
PoolGuard::putmay be used to explicitly put it back in the pool without relying on its destructor.Note that there is no guarantee provided about which value in the pool is returned. That is, calling get, dropping the guard (causing the value to go back into the pool) and then calling get again is not guaranteed to return the same value received in the first
getcall.
impl<T> Any for Pool<T, F>
fn type_id(self: &Self) -> TypeId
impl<T> Borrow for Pool<T, F>
fn borrow(self: &Self) -> &T
impl<T> BorrowMut for Pool<T, F>
fn borrow_mut(self: &mut Self) -> &mut T
impl<T> From for Pool<T, F>
fn from(t: T) -> TReturns the argument unchanged.
impl<T, F> Freeze for Pool<T, F>
impl<T, F> RefUnwindSafe for Pool<T, F>
impl<T, F> Send for Pool<T, F>
impl<T, F> Sync for Pool<T, F>
impl<T, F> Unpin for Pool<T, F>
impl<T, F> UnsafeUnpin for Pool<T, F>
impl<T, F> UnwindSafe for Pool<T, F>
impl<T, U> Into for Pool<T, F>
fn into(self: Self) -> UCalls
U::from(self).That is, this conversion is whatever the implementation of
[From]<T> for Uchooses to do.
impl<T, U> TryFrom for Pool<T, F>
fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
impl<T, U> TryInto for Pool<T, F>
fn try_into(self: Self) -> Result<U, <U as TryFrom<T>>::Error>
impl<T: core::fmt::Debug, F> Debug for Pool<T, F>
fn fmt(self: &Self, f: &mut Formatter<'_>) -> Result