1#![cfg(feature = "tbox")]
2use std::borrow::Borrow;
3use std::borrow::BorrowMut;
4use std::cmp::Ordering;
5use std::fmt;
6use std::hash::Hash;
7use std::hash::Hasher;
8use std::marker::PhantomData;
9use std::ops::Deref;
10use std::ops::DerefMut;
11
12use crate::*;
13
14#[cfg(feature = "st_tbox")]
16#[doc(hidden)]
17pub type TScPool<T> = STPool<ScInner<T>>;
18
19#[cfg(not(feature = "st_tbox"))]
20#[doc(hidden)]
21pub type TScPool<T> = TPool<ScInner<T>>;
22
23#[macro_export]
39macro_rules! define_tsc_pool {
40 ($TAG:ty:$T:ty) => {
41 $crate::assoc_static!($TAG: $T, $crate::TScPool<$T> = $crate::TScPool::new());
42 };
43}
44
45pub struct TSc<T, TAG>
48where
49 T: AssocStatic<TScPool<T>, TAG> + 'static,
50 TAG: 'static,
51{
52 slot: Slot<ScInner<T>, Mutable>,
53 tag: PhantomData<TAG>,
54}
55
56impl<T, TAG> TSc<T, TAG>
57where
58 T: AssocStatic<TScPool<T>, TAG> + 'static,
59 TAG: 'static,
60{
61 #[must_use]
63 pub fn strong_count(this: &Self) -> usize {
64 this.slot.get().get_strong()
65 }
66}
67
68impl<T, TAG> TSc<T, TAG>
69where
70 T: AssocStatic<TScPool<T>, TAG> + 'static,
71 TAG: 'static,
72{
73 #[inline]
75 pub fn new(t: T, _tag: TAG) -> Self {
76 Self {
77 slot: T::get_static().alloc(ScInner::new(t)).for_mutation(),
78 tag: PhantomData,
79 }
80 }
81
82 #[inline]
84 pub fn new_notag(t: T) -> Self {
85 Self {
86 slot: T::get_static().alloc(ScInner::new(t)).for_mutation(),
87 tag: PhantomData,
88 }
89 }
90}
91
92impl<T, TAG> Default for TSc<T, TAG>
93where
94 T: AssocStatic<TScPool<T>, TAG> + 'static + Default,
95 TAG: 'static,
96{
97 #[inline]
99 fn default() -> Self {
100 TSc::new_notag(T::default())
101 }
102}
103
104impl<T, TAG> Clone for TSc<T, TAG>
105where
106 T: AssocStatic<TScPool<T>, TAG> + 'static,
107 TAG: 'static,
108{
109 #[must_use]
110 fn clone(&self) -> Self {
111 self.slot.get().inc_strong();
112 unsafe {
113 Self {
114 slot: self.slot.copy(),
115 tag: PhantomData,
116 }
117 }
118 }
119}
120
121impl<T, TAG> Drop for TSc<T, TAG>
122where
123 T: AssocStatic<TScPool<T>, TAG> + 'static,
124 TAG: 'static,
125{
126 #[inline]
127 fn drop(&mut self) {
128 let mslot = self.slot.get_mut();
129
130 mslot.dec_strong();
131
132 if mslot.get_strong() == 0 {
133 unsafe {
134 T::get_static().free_by_ref(&mut self.slot);
135 }
136 }
137 }
138}
139
140impl<T, TAG> Deref for TSc<T, TAG>
141where
142 T: AssocStatic<TScPool<T>, TAG> + 'static,
143 TAG: 'static,
144{
145 type Target = T;
146
147 #[inline]
148 fn deref(&self) -> &<Self as Deref>::Target {
149 unsafe { self.slot.get().data.assume_init_ref() }
150 }
151}
152
153impl<T, TAG> DerefMut for TSc<T, TAG>
154where
155 T: AssocStatic<TScPool<T>, TAG> + 'static,
156 TAG: 'static,
157{
158 #[inline]
159 fn deref_mut(&mut self) -> &mut <Self as Deref>::Target {
160 unsafe { self.slot.get_mut().data.assume_init_mut() }
161 }
162}
163
164impl<T, TAG> Borrow<T> for TSc<T, TAG>
165where
166 T: AssocStatic<TScPool<T>, TAG> + 'static,
167 TAG: 'static,
168{
169 #[inline]
170 fn borrow(&self) -> &T {
171 unsafe { self.slot.get().data.assume_init_ref() }
172 }
173}
174
175impl<T, TAG> BorrowMut<T> for TSc<T, TAG>
176where
177 T: AssocStatic<TScPool<T>, TAG> + 'static,
178 TAG: 'static,
179{
180 #[inline]
181 fn borrow_mut(&mut self) -> &mut T {
182 unsafe { self.slot.get_mut().data.assume_init_mut() }
183 }
184}
185
186impl<T, TAG> AsRef<T> for TSc<T, TAG>
187where
188 T: AssocStatic<TScPool<T>, TAG> + 'static,
189 TAG: 'static,
190{
191 #[inline]
192 fn as_ref(&self) -> &T {
193 unsafe { self.slot.get().data.assume_init_ref() }
194 }
195}
196
197impl<T, TAG> AsMut<T> for TSc<T, TAG>
198where
199 T: AssocStatic<TScPool<T>, TAG> + 'static,
200 TAG: 'static,
201{
202 #[inline]
203 fn as_mut(&mut self) -> &mut T {
204 unsafe { self.slot.get_mut().data.assume_init_mut() }
205 }
206}
207
208impl<T: PartialEq, TAG> PartialEq for TSc<T, TAG>
209where
210 T: AssocStatic<TScPool<T>, TAG> + 'static,
211 TAG: 'static,
212{
213 #[inline]
214 fn eq(&self, other: &Self) -> bool {
215 PartialEq::eq(&**self, &**other)
216 }
217}
218
219impl<T: PartialOrd, TAG> PartialOrd for TSc<T, TAG>
220where
221 T: AssocStatic<TScPool<T>, TAG> + 'static,
222 TAG: 'static,
223{
224 #[inline]
225 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
226 PartialOrd::partial_cmp(&**self, &**other)
227 }
228 #[inline]
229 fn lt(&self, other: &Self) -> bool {
230 PartialOrd::lt(&**self, &**other)
231 }
232 #[inline]
233 fn le(&self, other: &Self) -> bool {
234 PartialOrd::le(&**self, &**other)
235 }
236 #[inline]
237 fn ge(&self, other: &Self) -> bool {
238 PartialOrd::ge(&**self, &**other)
239 }
240 #[inline]
241 fn gt(&self, other: &Self) -> bool {
242 PartialOrd::gt(&**self, &**other)
243 }
244}
245
246impl<T: Ord, TAG> Ord for TSc<T, TAG>
247where
248 T: AssocStatic<TScPool<T>, TAG> + 'static,
249 TAG: 'static,
250{
251 #[inline]
252 fn cmp(&self, other: &Self) -> Ordering {
253 Ord::cmp(&**self, &**other)
254 }
255}
256
257impl<T: Eq, TAG> Eq for TSc<T, TAG>
258where
259 T: AssocStatic<TScPool<T>, TAG> + 'static,
260 TAG: 'static,
261{
262}
263
264impl<T: Hash, TAG> Hash for TSc<T, TAG>
265where
266 T: AssocStatic<TScPool<T>, TAG> + 'static,
267 TAG: 'static,
268{
269 fn hash<H: Hasher>(&self, state: &mut H) {
270 (**self).hash(state);
271 }
272}
273
274impl<T: Hasher, TAG> Hasher for TSc<T, TAG>
275where
276 T: AssocStatic<TScPool<T>, TAG> + 'static,
277 TAG: 'static,
278{
279 fn finish(&self) -> u64 {
280 (**self).finish()
281 }
282 fn write(&mut self, bytes: &[u8]) {
283 (**self).write(bytes);
284 }
285 fn write_u8(&mut self, i: u8) {
286 (**self).write_u8(i);
287 }
288 fn write_u16(&mut self, i: u16) {
289 (**self).write_u16(i);
290 }
291 fn write_u32(&mut self, i: u32) {
292 (**self).write_u32(i);
293 }
294 fn write_u64(&mut self, i: u64) {
295 (**self).write_u64(i);
296 }
297 fn write_u128(&mut self, i: u128) {
298 (**self).write_u128(i);
299 }
300 fn write_usize(&mut self, i: usize) {
301 (**self).write_usize(i);
302 }
303 fn write_i8(&mut self, i: i8) {
304 (**self).write_i8(i);
305 }
306 fn write_i16(&mut self, i: i16) {
307 (**self).write_i16(i);
308 }
309 fn write_i32(&mut self, i: i32) {
310 (**self).write_i32(i);
311 }
312 fn write_i64(&mut self, i: i64) {
313 (**self).write_i64(i);
314 }
315 fn write_i128(&mut self, i: i128) {
316 (**self).write_i128(i);
317 }
318 fn write_isize(&mut self, i: isize) {
319 (**self).write_isize(i);
320 }
321 }
328
329impl<T: fmt::Display, TAG> fmt::Display for TSc<T, TAG>
330where
331 T: AssocStatic<TScPool<T>, TAG> + 'static,
332 TAG: 'static,
333{
334 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
335 fmt::Display::fmt(&**self, f)
336 }
337}
338
339impl<T: fmt::Debug, TAG> fmt::Debug for TSc<T, TAG>
340where
341 T: AssocStatic<TScPool<T>, TAG> + 'static,
342 TAG: 'static,
343{
344 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
345 fmt::Debug::fmt(&**self, f)
346 }
347}
348
349impl<T, TAG> fmt::Pointer for TSc<T, TAG>
350where
351 T: AssocStatic<TScPool<T>, TAG> + 'static,
352 TAG: 'static,
353{
354 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
355 let ptr: *const T = &**self;
356 fmt::Pointer::fmt(&ptr, f)
357 }
358}
359
360#[cfg(test)]
361mod tests {
362 use crate::*;
363 use serial_test::serial;
364
365 define_tsc_pool!((): &'static str);
366 define_tsc_pool!((): u64);
367
368 #[test]
369 #[ignore]
370 #[serial]
371 fn smoke() {
372 TBox::<&'static str, ()>::pool()
373 .acquire()
374 .expect("some other thread owns the pool");
375
376 let _mybox = TSc::new("TBoxed", ());
377
378 TBox::<&'static str, ()>::pool()
379 .release()
380 .expect("thread does not own the pool");
381 }
382}