1use core::{
19 cmp::Ordering,
20 hash::{Hash, Hasher},
21 marker::PhantomData,
22 num::NonZeroU64,
23};
24
25use crate::{
26 pool::PoolMut,
27 scalar::{OpaqueScalar, ScalarAllocator},
28 Identifier, OneShotIdentifier, Token,
29};
30
31crate::scalar_allocator! {
32 pub struct Global(NonZeroU64);
36}
37
38#[cfg(feature = "std")]
39#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
40crate::scalar_allocator! {
41 pub thread_local struct ThreadLocal(NonZeroU64);
45}
46
47#[derive(Debug)]
52pub struct Dynamic<A: ScalarAllocator = Global, P: PoolMut<A> = ()> {
53 scalar: A::Scalar,
54 pool: P,
55 auto: PhantomData<A::AutoTraits>,
56}
57
58#[derive(Debug)]
60#[repr(transparent)]
61pub struct DynamicToken<A: ScalarAllocator = Global> {
62 scalar: A::Scalar,
63 auto: PhantomData<A::AutoTraits>,
64}
65
66impl<A: ScalarAllocator<Scalar = ()>> Default for DynamicToken<A> {
67 #[inline]
68 fn default() -> Self { Self::NEW }
69}
70
71impl<A: ScalarAllocator<Scalar = ()>> DynamicToken<A> {
72 pub const NEW: Self = Self {
74 scalar: (),
75 auto: PhantomData,
76 };
77}
78
79impl<A: ScalarAllocator> DynamicToken<A> {
80 #[inline]
81 pub fn new(scalar: A::Scalar) -> Self {
83 Self {
84 scalar,
85 auto: PhantomData,
86 }
87 }
88}
89
90impl Dynamic {
91 #[inline]
93 pub fn create() -> Self { Self::with_pool(()) }
94}
95
96impl<P: PoolMut<Global>> Dynamic<Global, P> {
97 #[inline]
98 pub fn with_pool(pool: P) -> Self { Self::with_alloc_and_pool(pool) }
100}
101
102impl<A: ScalarAllocator> Dynamic<A> {
103 #[inline]
104 pub fn with_alloc() -> Self { Self::with_alloc_and_pool(()) }
106}
107
108impl<A: ScalarAllocator, P: PoolMut<A>> Dynamic<A, P> {
109 #[inline]
110 pub fn with_alloc_and_pool(mut pool: P) -> Self {
112 Self {
113 scalar: pool.remove_mut().map(OpaqueScalar::into_inner).unwrap_or_else(A::alloc),
114 pool,
115 auto: PhantomData,
116 }
117 }
118}
119
120impl<A: ScalarAllocator, P: PoolMut<A>> Drop for Dynamic<A, P> {
121 #[inline]
122 fn drop(&mut self) { let _ = self.pool.insert_mut(unsafe { OpaqueScalar::new(self.scalar.clone()) }); }
123}
124
125impl<A: ScalarAllocator, P: PoolMut<A>> Dynamic<A, P> {
126 #[inline]
128 pub fn owns_token(&self, token: &DynamicToken<A>) -> bool { self.scalar == token.scalar }
129
130 #[inline]
132 pub fn token(&self) -> DynamicToken<A> {
133 DynamicToken {
134 scalar: self.scalar.clone(),
135 auto: PhantomData,
136 }
137 }
138}
139
140unsafe impl<A: ScalarAllocator> Token for DynamicToken<A> {}
141
142unsafe impl<A: ScalarAllocator> OneShotIdentifier for Dynamic<A> {}
143unsafe impl<A: ScalarAllocator, P: PoolMut<A>> Identifier for Dynamic<A, P> {
144 type Token = DynamicToken<A>;
145
146 #[inline]
147 fn owns_token(&self, token: &Self::Token) -> bool { self.owns_token(token) }
148
149 #[inline]
150 fn token(&self) -> Self::Token { self.token() }
151}
152
153impl<A: ScalarAllocator<Scalar = ()>> crate::Init for DynamicToken<A> {
154 const INIT: Self = Self {
155 auto: PhantomData,
156 scalar: (),
157 };
158}
159
160impl<A: ScalarAllocator<Scalar = ()>> crate::Trivial for DynamicToken<A> {}
161impl<A: ScalarAllocator> Copy for DynamicToken<A> where A::Scalar: Copy {}
162impl<A: ScalarAllocator> Clone for DynamicToken<A> {
163 #[inline]
164 fn clone(&self) -> Self {
165 Self {
166 scalar: self.scalar.clone(),
167 auto: PhantomData,
168 }
169 }
170}
171
172impl<A: ScalarAllocator> Eq for DynamicToken<A> {}
173impl<A: ScalarAllocator> PartialEq for DynamicToken<A> {
174 #[inline]
175 fn eq(&self, other: &Self) -> bool { self.scalar == other.scalar }
176}
177
178impl<A: ScalarAllocator> Hash for DynamicToken<A>
179where
180 A::Scalar: Hash,
181{
182 #[inline]
183 fn hash<H: Hasher>(&self, state: &mut H) { self.scalar.hash(state) }
184}
185
186impl<A: ScalarAllocator> PartialOrd for DynamicToken<A>
187where
188 A::Scalar: PartialOrd,
189{
190 #[inline]
191 fn partial_cmp(&self, other: &Self) -> Option<Ordering> { self.scalar.partial_cmp(&other.scalar) }
192}
193
194impl<A: ScalarAllocator> Ord for DynamicToken<A>
195where
196 A::Scalar: Ord,
197{
198 #[inline]
199 fn cmp(&self, other: &Self) -> Ordering { self.scalar.cmp(&other.scalar) }
200}