Lines Matching full:pool

1 // This module provides a relatively simple thread-safe pool of reusable
4 // costly, in the case where a pool is accessed by the first thread that tried
14 // using the 'thread_local' crate to implement the pool below.
16 // (2) represents a naive pool implemented completely via Mutex<Vec<T>>. There
20 // fast because a Box<T> is much smaller than the T we use with a Pool in this
38 // have used a regex, where as the pool below scales to the number of threads
40 // since we own the pool data structure below, we can add contraction if a
46 // threads. In contrast, the pool below scales with the total number of threads
47 // *simultaneously* using the pool. The hope is that this uses less memory
72 // thread ID might result in more than one thread "owning" a pool,
87 /// The type of the function used to create values in a pool when the pool is
92 /// A simple thread safe pool for reusing values.
95 /// value is automatically put back in the pool.
97 /// A Pool<T> impls Sync when T is Send (even if it's not Sync). This means
98 /// that T can use interior mutability. This is possible because a pool is
101 /// Currently, a pool never contracts in size. Its size is proportional to the
103 pub struct Pool<T> { struct
104 /// A stack of T values to hand out. These are used when a Pool is
110 /// The ID of the thread that owns this pool. The owner is the thread
120 /// the Pool. argument
124 // SAFETY: Since we want to use a Pool from multiple threads simultaneously argument
125 // behind an Arc, we need for it to be Sync. In cases where T is sync, Pool<T>
126 // would be Sync. However, since we use a Pool to store mutable scratch space,
128 // Sync. So what we *really* want is for our Pool<T> to by Sync even when T is
131 // The only non-sync aspect of a Pool is its 'owner_val' field, which is used
132 // to implement faster access to a pool value in the common case of a pool
140 // that created the Pool. Since this can only ever be one thread, it follows
142 // is safe to declare that Pool<T> is Sync when T is Send.
145 // thread that tries to get a value out of a Pool. However, the current
154 unsafe impl<T: Send> Sync for Pool<T> {} implementation
156 impl<T: ::std::fmt::Debug> ::std::fmt::Debug for Pool<T> { implementation
158 f.debug_struct("Pool") in fmt()
166 /// A guard that is returned when a caller requests a value from the pool.
169 /// in the pool once it's dropped.
172 /// The pool that this guard is attached to.
173 pool: &'a Pool<T>, field
175 /// which case, the value is retrieved from 'pool.owner_val'.
179 impl<T: Send> Pool<T> { impl
180 /// Create a new pool. The given closure is used to create values in the
181 /// pool when necessary.
182 pub fn new(create: CreateFn<T>) -> Pool<T> { in new()
185 Pool { stack: Mutex::new(vec![]), create, owner, owner_val } in new()
188 /// Get a value from the pool. The caller is guaranteed to have exclusive
192 /// pool is returned. That is, calling get, dropping the guard (causing
193 /// the value to go back into the pool) and then calling get again is NOT
198 // pool. Or stated differently, whether it is the first thread that in get()
199 // tried to extract a value from the pool. If it is, then we can return in get()
218 /// If the pool has no owner, then this will set the owner.
224 // The sentinel 0 value means this pool is not yet owned. We in get_slow()
241 /// Puts a value back into the pool. Callers don't need to call this. Once
243 /// pool automatically.
251 PoolGuard { pool: self, value: None } in guard_owned()
254 /// Create a guard that contains a value from the pool's stack.
256 PoolGuard { pool: self, value: Some(value) } in guard_stack()
264 None => &self.pool.owner_val, in value()
274 self.pool.put(value); in drop()
290 has_oibits::<Pool<ProgramCache>>(); in oibits()
293 // Tests that Pool implements the "single owner" optimization. That is, the
294 // thread that first accesses the pool gets its own copy, while all other
301 let pool: Arc<Pool<RefCell<Vec<char>>>> = in thread_owner_optimization() localVariable
302 Arc::new(Pool::new(Box::new(|| RefCell::new(vec!['a'])))); in thread_owner_optimization()
303 pool.get().value().borrow_mut().push('x'); in thread_owner_optimization()
305 let pool1 = pool.clone(); in thread_owner_optimization()
312 let pool2 = pool.clone(); in thread_owner_optimization()
324 // we stuffed in the pool before spawning the threads. But since in thread_owner_optimization()
325 // neither thread was first to access the pool, and because of the in thread_owner_optimization()
327 // the special owned pool value. in thread_owner_optimization()
330 // Pool's API.) in thread_owner_optimization()
331 assert_eq!(vec!['a', 'x'], *pool.get().value().borrow()); in thread_owner_optimization()