pui_core/
pool.rs

1//! A pool of ids that can be used to reuse ids in [`Dynamic`](crate::dynamic::Dynamic).
2
3use crate::scalar::{OpaqueScalar, ScalarAllocator};
4
5mod ext;
6mod flag;
7mod sequence;
8
9pub use flag::Flag;
10pub use sequence::Sequence;
11
12#[doc(hidden)]
13pub mod export {
14    #[cfg(feature = "std")]
15    pub use super::ext::LocalKey;
16}
17
18#[doc(hidden)]
19#[macro_export]
20macro_rules! __global_pool {
21    ($name:ident($imp:ty)) => {
22        impl $crate::Init for $name {
23            const INIT: Self = Self;
24        }
25
26        const _: () = {
27            static __IMP_POOL: $imp = $crate::Init::INIT;
28
29            impl<A: $crate::scalar::ScalarAllocator> $crate::pool::PoolMut<A> for $name
30            where
31                $imp: $crate::pool::Pool<A>,
32            {
33                fn insert_mut(
34                    &mut self,
35                    scalar: $crate::scalar::OpaqueScalar<A>,
36                ) -> Option<$crate::scalar::OpaqueScalar<A>> {
37                    $crate::pool::Pool::insert(&__IMP_POOL, scalar)
38                }
39
40                fn remove_mut(&mut self) -> Option<$crate::scalar::OpaqueScalar<A>> {
41                    $crate::pool::Pool::remove(&__IMP_POOL)
42                }
43            }
44
45            impl<A: $crate::scalar::ScalarAllocator> $crate::pool::Pool<A> for $name
46            where
47                $imp: $crate::pool::Pool<A>,
48            {
49                fn insert(&self, scalar: $crate::scalar::OpaqueScalar<A>) -> Option<$crate::scalar::OpaqueScalar<A>> {
50                    $crate::pool::Pool::insert(&__IMP_POOL, scalar)
51                }
52
53                fn remove(&self) -> Option<$crate::scalar::OpaqueScalar<A>> { $crate::pool::Pool::remove(&__IMP_POOL) }
54            }
55        };
56    };
57    (thread_local $name:ident($imp:ty)) => {
58        impl $crate::Init for $name {
59            const INIT: Self = Self;
60        }
61
62        const _: () = {
63            $crate::export::thread_local! {
64                static __IMP_POOL: $imp = $crate::export::Default::default();
65            }
66
67            impl<A: $crate::scalar::ScalarAllocator> $crate::pool::PoolMut<A> for $name
68            where
69                $imp: $crate::pool::Pool<A>,
70            {
71                fn insert_mut(
72                    &mut self,
73                    scalar: $crate::scalar::OpaqueScalar<A>,
74                ) -> Option<$crate::scalar::OpaqueScalar<A>> {
75                    $crate::pool::Pool::insert(&$crate::pool::export::LocalKey(&__IMP_POOL), scalar)
76                }
77
78                fn remove_mut(&mut self) -> Option<$crate::scalar::OpaqueScalar<A>> {
79                    $crate::pool::Pool::remove(&$crate::pool::export::LocalKey(&__IMP_POOL))
80                }
81            }
82
83            impl<A: $crate::scalar::ScalarAllocator> $crate::pool::Pool<A> for $name
84            where
85                $imp: $crate::pool::Pool<A>,
86            {
87                fn insert(&self, scalar: $crate::scalar::OpaqueScalar<A>) -> Option<$crate::scalar::OpaqueScalar<A>> {
88                    $crate::pool::Pool::insert(&$crate::pool::export::LocalKey(&__IMP_POOL), scalar)
89                }
90
91                fn remove(&self) -> Option<$crate::scalar::OpaqueScalar<A>> {
92                    $crate::pool::Pool::remove(&$crate::pool::export::LocalKey(&__IMP_POOL))
93                }
94            }
95        };
96    };
97}
98
99/// Create a new type that implements [`Pool`](crate::pool::Pool) and [`PoolMut`](crate::pool::PoolMut)
100/// that can be used with [`Dynamic`](crate::dynamic::Dynamic)
101///
102/// For example,
103///
104/// ```
105/// # #[cfg(feature = "std")]
106/// pui_core::global_pool! {
107///     pub struct MyPool(pui_core::pool::SyncStackPool<pui_core::dynamic::Global>);
108/// }
109///
110/// let _my_pool = MyPool;
111/// ```
112///
113/// will generate a global pool that is backed by a `SyncStackPool`, and holds `Global`s
114#[macro_export]
115macro_rules! global_pool {
116    (
117        $(#[$meta:meta])*
118        $v:vis struct $name:ident($imp:ty);
119    ) => {
120        $(#[$meta])*
121        $v struct $name;
122
123        $crate::__global_pool!{$name($imp)}
124    };
125    (
126        $(#[$meta:meta])*
127        $v:vis thread_local struct $name:ident($imp:ty);
128    ) => {
129        $(#[$meta])*
130        $v struct $name;
131
132        $crate::__global_pool!{thread_local $name($imp)}
133    };
134}
135
136#[cfg(feature = "alloc")]
137cfg_if::cfg_if! {
138    if #[cfg(feature = "parking_lot")] {
139        use parking_lot::Mutex;
140        use std::vec::Vec;
141        use std::collections::VecDeque;
142
143        /// A thread safe stack-pool, it returns scalars in LIFO order
144        #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
145        pub struct SyncStackPool<T: ScalarAllocator>(Mutex<Vec<crate::scalar::OpaqueScalar<T>>>);
146
147        /// A thread safe queue-pool, it returns scalars in FIFO order
148        #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
149        pub struct SyncQueuePool<T: ScalarAllocator>(once_cell::sync::Lazy<Mutex<VecDeque<crate::scalar::OpaqueScalar<T>>>>);
150    } else if #[cfg(feature = "std")] {
151        use std::sync::Mutex;
152        use std::collections::VecDeque;
153
154        /// A thread safe stack-pool, it returns scalars in LIFO order
155        #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
156        pub struct SyncStackPool<T: ScalarAllocator>(once_cell::sync::Lazy<Mutex<Vec<crate::scalar::OpaqueScalar<T>>>>);
157
158        /// A thread safe queue-pool, it returns scalars in FIFO order
159        #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
160        pub struct SyncQueuePool<T: ScalarAllocator>(once_cell::sync::Lazy<Mutex<VecDeque<crate::scalar::OpaqueScalar<T>>>>);
161    }
162}
163
164/// A pool of ids that can be used to reuse ids in [`Dynamic`](crate::dynamic::Dynamic).
165pub trait PoolMut<A: ScalarAllocator> {
166    /// Put a new id into the pool
167    fn insert_mut(&mut self, scalar: OpaqueScalar<A>) -> Option<OpaqueScalar<A>>;
168
169    /// Take an id out of the pool
170    fn remove_mut(&mut self) -> Option<OpaqueScalar<A>>;
171}
172
173/// A pool of ids that can be used to reuse ids in [`Dynamic`](crate::dynamic::Dynamic).
174pub trait Pool<A: ScalarAllocator>: PoolMut<A> {
175    /// Put a new id into the pool
176    fn insert(&self, scalar: OpaqueScalar<A>) -> Option<OpaqueScalar<A>>;
177
178    /// Take an id out of the pool
179    fn remove(&self) -> Option<OpaqueScalar<A>>;
180}
181
182impl crate::Init for () {
183    const INIT: Self = ();
184}
185
186impl<A: ScalarAllocator> PoolMut<A> for () {
187    fn insert_mut(&mut self, scalar: OpaqueScalar<A>) -> Option<OpaqueScalar<A>> { Some(scalar) }
188
189    fn remove_mut(&mut self) -> Option<OpaqueScalar<A>> { None }
190}
191
192impl<A: ScalarAllocator> Pool<A> for () {
193    fn insert(&self, scalar: OpaqueScalar<A>) -> Option<OpaqueScalar<A>> { Some(scalar) }
194
195    fn remove(&self) -> Option<OpaqueScalar<A>> { None }
196}
197
198impl<P: ?Sized + PoolMut<A>, A: ScalarAllocator> PoolMut<A> for &mut P {
199    fn insert_mut(&mut self, scalar: OpaqueScalar<A>) -> Option<OpaqueScalar<A>> { P::insert_mut(self, scalar) }
200
201    fn remove_mut(&mut self) -> Option<OpaqueScalar<A>> { P::remove_mut(self) }
202}
203
204impl<P: ?Sized + Pool<A>, A: ScalarAllocator> Pool<A> for &mut P {
205    fn insert(&self, scalar: OpaqueScalar<A>) -> Option<OpaqueScalar<A>> { P::insert(self, scalar) }
206
207    fn remove(&self) -> Option<OpaqueScalar<A>> { P::remove(self) }
208}
209
210impl<P: ?Sized + Pool<A>, A: ScalarAllocator> PoolMut<A> for &P {
211    fn insert_mut(&mut self, scalar: OpaqueScalar<A>) -> Option<OpaqueScalar<A>> { P::insert(self, scalar) }
212
213    fn remove_mut(&mut self) -> Option<OpaqueScalar<A>> { P::remove(self) }
214}
215
216impl<P: ?Sized + Pool<A>, A: ScalarAllocator> Pool<A> for &P {
217    fn insert(&self, scalar: OpaqueScalar<A>) -> Option<OpaqueScalar<A>> { P::insert(self, scalar) }
218
219    fn remove(&self) -> Option<OpaqueScalar<A>> { P::remove(self) }
220}