unique_pointer/
refcounter.rs1use std::alloc::Layout;
2use std::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
3use std::convert::{AsMut, AsRef};
4use std::marker::PhantomData;
5use std::ops::{AddAssign, Deref, DerefMut, SubAssign};
6pub struct RefCounter {
15 data: *mut usize,
16}
17
18impl RefCounter {
19 pub fn null() -> RefCounter {
22 RefCounter {
23 data: std::ptr::null_mut::<usize>(),
24 }
25 }
26
27 pub fn new() -> RefCounter {
29 let mut ref_counter = RefCounter::null();
30 ref_counter.incr();
31 ref_counter
32 }
33
34 pub fn reset(&mut self) {
37 self.write(1);
38 }
39
40 pub fn incr(&mut self) {
42 self.incr_by(1);
43 }
44
45 pub fn incr_by(&mut self, by: usize) {
47 self.write(self.read() + by);
48 }
49
50 pub fn decr(&mut self) {
52 self.decr_by(1);
53 }
54
55 pub fn decr_by(&mut self, by: usize) {
57 let data = self.read();
58 if data >= by {
59 self.write(data - by);
60 }
61 }
62
63 pub fn drain(&mut self) {
67 if !self.data.is_null() {
68 unsafe {
69 self.data.drop_in_place();
70 }
71 }
72 }
73
74 pub fn read(&self) -> usize {
75 if self.data.is_null() {
76 0
77 } else {
78 let mut ptr = self.cast_const();
79 unsafe { ptr.read() }
80 }
81 }
82
83 fn alloc(&self) {
84 if !self.data.is_null() {
85 return;
86 }
87
88 let layout = Layout::new::<usize>();
89 let ptr = unsafe {
90 let ptr = std::alloc::alloc(layout);
91 if ptr.is_null() {
92 std::alloc::handle_alloc_error(layout);
93 }
94 ptr as *mut usize
95 };
96 let mut up = unsafe { self.meta_mut() };
97 up.data = ptr;
98 up.write(1);
99 }
100
101 pub fn write(&mut self, data: usize) {
104 self.alloc();
105 let mut ptr = self.cast_mut();
106 unsafe {
107 ptr.write(data);
108 }
109 }
110
111 pub fn inner_ref<'c>(&self) -> &'c usize {
115 if self.data.is_null() {
116 &0
117 } else {
118 let ptr = self.cast_const();
119 unsafe { &*ptr }
120 }
121 }
122
123 pub fn inner_mut<'c>(&mut self) -> &'c mut usize {
127 if self.data.is_null() {
128 self.write(0);
129 }
130 let mut ptr = self.cast_mut();
131 unsafe { &mut *ptr }
132 }
133}
134impl RefCounter {
135 fn cast_mut(&self) -> *mut usize {
137 self.data
138 }
139
140 fn cast_const(&self) -> *const usize {
141 self.data.cast_const()
142 }
143}
144impl From<usize> for RefCounter {
145 fn from(refs: usize) -> RefCounter {
146 let mut ref_counter = RefCounter::new();
147 ref_counter.write(refs);
148 ref_counter
149 }
150}
151impl AsRef<usize> for RefCounter {
152 fn as_ref(&self) -> &usize {
153 self.inner_ref()
154 }
155}
156impl AsMut<usize> for RefCounter {
157 fn as_mut(&mut self) -> &mut usize {
158 if self.data.is_null() {
159 self.write(0);
160 }
161 let mut ptr = self.cast_mut();
162 unsafe { &mut *ptr }
163 }
164}
165impl Deref for RefCounter {
166 type Target = usize;
167
168 fn deref(&self) -> &usize {
169 self.inner_ref()
170 }
171}
172impl DerefMut for RefCounter {
173 fn deref_mut(&mut self) -> &mut usize {
174 self.inner_mut()
175 }
176}
177
178impl Drop for RefCounter {
179 fn drop(&mut self) {
180 self.drain()
181 }
182}
183
184impl Clone for RefCounter {
185 fn clone(&self) -> RefCounter {
186 let mut clone = RefCounter::new();
187 clone.data = self.data;
188 clone
189 }
190}
191
192impl std::fmt::Debug for RefCounter {
193 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
194 write!(
195 f,
196 "{}",
197 [
198 format!("RefCounter@"),
199 format!("{:016x}", self.data.addr()),
200 format!("[data={}]", self.read()),
201 ]
202 .join("")
203 )
204 }
205}
206impl std::fmt::Display for RefCounter {
207 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
208 write!(f, "{}", self.read())
209 }
210}
211
212#[allow(invalid_reference_casting)]
213impl<'c> RefCounter {
214 unsafe fn meta_mut(&'c self) -> &'c mut RefCounter {
217 unsafe {
218 let ptr = self.meta_mut_ptr();
219 let mut up = &mut *ptr;
220 std::mem::transmute::<&mut RefCounter, &'c mut RefCounter>(up)
221 }
222 }
223
224 unsafe fn meta_mut_ptr(&self) -> *mut RefCounter {
226 let ptr = self as *const RefCounter;
227 unsafe {
228 let ptr: *mut RefCounter =
229 std::mem::transmute::<*const RefCounter, *mut RefCounter>(ptr);
230 ptr
231 }
232 }
233}
234
235impl AddAssign<usize> for RefCounter {
236 fn add_assign(&mut self, other: usize) {
237 self.incr_by(other)
238 }
239}
240
241impl SubAssign<usize> for RefCounter {
242 fn sub_assign(&mut self, other: usize) {
243 self.decr_by(other)
244 }
245}
246
247impl PartialOrd<usize> for RefCounter {
248 fn partial_cmp(&self, other: &usize) -> Option<Ordering> {
249 self.read().partial_cmp(other)
250 }
251}
252
253impl PartialEq<usize> for RefCounter {
254 fn eq(&self, other: &usize) -> bool {
255 self.read().eq(other)
256 }
257}
258
259impl PartialOrd for RefCounter {
260 fn partial_cmp(&self, other: &RefCounter) -> Option<Ordering> {
261 self.read().partial_cmp(other.inner_ref())
262 }
263}
264
265impl Ord for RefCounter {
266 fn cmp(&self, other: &RefCounter) -> Ordering {
267 self.read().cmp(other.inner_ref())
268 }
269}
270
271impl PartialEq for RefCounter {
272 fn eq(&self, other: &RefCounter) -> bool {
273 self.read().eq(other.inner_ref())
274 }
275}
276
277impl Eq for RefCounter {}