sharded_slab/
sync.rs

1pub(crate) use self::inner::*;
2
3#[cfg(all(loom, any(test, feature = "loom")))]
4mod inner {
5    pub(crate) mod atomic {
6        pub use loom::sync::atomic::*;
7        pub use std::sync::atomic::Ordering;
8    }
9    pub(crate) use loom::{
10        cell::UnsafeCell, hint, lazy_static, sync::Mutex, thread::yield_now, thread_local,
11    };
12
13    pub(crate) mod alloc {
14        #![allow(dead_code)]
15        use loom::alloc;
16        use std::fmt;
17        /// Track allocations, detecting leaks
18        ///
19        /// This is a version of `loom::alloc::Track` that adds a missing
20        /// `Default` impl.
21        pub struct Track<T>(alloc::Track<T>);
22
23        impl<T> Track<T> {
24            /// Track a value for leaks
25            #[inline(always)]
26            pub fn new(value: T) -> Track<T> {
27                Track(alloc::Track::new(value))
28            }
29
30            /// Get a reference to the value
31            #[inline(always)]
32            pub fn get_ref(&self) -> &T {
33                self.0.get_ref()
34            }
35
36            /// Get a mutable reference to the value
37            #[inline(always)]
38            pub fn get_mut(&mut self) -> &mut T {
39                self.0.get_mut()
40            }
41
42            /// Stop tracking the value for leaks
43            #[inline(always)]
44            pub fn into_inner(self) -> T {
45                self.0.into_inner()
46            }
47        }
48
49        impl<T: fmt::Debug> fmt::Debug for Track<T> {
50            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
51                self.0.fmt(f)
52            }
53        }
54
55        impl<T: Default> Default for Track<T> {
56            fn default() -> Self {
57                Self::new(T::default())
58            }
59        }
60    }
61}
62
63#[cfg(not(all(loom, any(feature = "loom", test))))]
64mod inner {
65    #![allow(dead_code)]
66    pub(crate) use lazy_static::lazy_static;
67    pub(crate) use std::{
68        sync::{atomic, Mutex},
69        thread::yield_now,
70        thread_local,
71    };
72
73    pub(crate) mod hint {
74        #[inline(always)]
75        pub(crate) fn spin_loop() {
76            // MSRV: std::hint::spin_loop() stabilized in 1.49.0
77            #[allow(deprecated)]
78            super::atomic::spin_loop_hint()
79        }
80    }
81
82    #[derive(Debug)]
83    pub(crate) struct UnsafeCell<T>(std::cell::UnsafeCell<T>);
84
85    impl<T> UnsafeCell<T> {
86        pub fn new(data: T) -> UnsafeCell<T> {
87            UnsafeCell(std::cell::UnsafeCell::new(data))
88        }
89
90        #[inline(always)]
91        pub fn with<F, R>(&self, f: F) -> R
92        where
93            F: FnOnce(*const T) -> R,
94        {
95            f(self.0.get())
96        }
97
98        #[inline(always)]
99        pub fn with_mut<F, R>(&self, f: F) -> R
100        where
101            F: FnOnce(*mut T) -> R,
102        {
103            f(self.0.get())
104        }
105    }
106
107    pub(crate) mod alloc {
108        /// Track allocations, detecting leaks
109        #[derive(Debug, Default)]
110        pub struct Track<T> {
111            value: T,
112        }
113
114        impl<T> Track<T> {
115            /// Track a value for leaks
116            #[inline(always)]
117            pub fn new(value: T) -> Track<T> {
118                Track { value }
119            }
120
121            /// Get a reference to the value
122            #[inline(always)]
123            pub fn get_ref(&self) -> &T {
124                &self.value
125            }
126
127            /// Get a mutable reference to the value
128            #[inline(always)]
129            pub fn get_mut(&mut self) -> &mut T {
130                &mut self.value
131            }
132
133            /// Stop tracking the value for leaks
134            #[inline(always)]
135            pub fn into_inner(self) -> T {
136                self.value
137            }
138        }
139    }
140}