1use crate::{Pointer, SmartPointer};
59use alloc::boxed::Box;
60use atomic_traits::{
61 Atomic, NumOps,
62 fetch::{Add, Sub},
63};
64use core::fmt;
65use core::marker::PhantomData;
66use core::ops::Deref;
67use core::ptr::NonNull;
68use core::sync::atomic::{
69 Ordering::{Acquire, Relaxed, Release},
70 fence,
71};
72
73pub unsafe trait IrcItem<Tag>: Sized + Send + Sync
81where
82 <Self::Counter as Atomic>::Type: From<u8> + Into<usize> + PartialEq,
83{
84 type Counter: NumOps;
86
87 fn counter(&self) -> &Self::Counter;
89
90 #[allow(clippy::boxed_local)]
95 #[inline(always)]
96 fn on_drop(_this: Box<Self>) {}
97
98 #[inline]
99 fn strong_count(&self) -> usize {
100 self.counter().load(Relaxed).into()
101 }
102}
103
104pub struct Irc<T: IrcItem<Tag>, Tag> {
108 inner: NonNull<T>,
109 _phan: PhantomData<fn(&Tag)>,
110}
111
112impl<T: IrcItem<Tag>, Tag> Irc<T, Tag> {
113 #[inline]
117 pub fn new(inner: T) -> Self {
118 inner.counter().store(1u8.into(), Relaxed);
119 Self {
120 inner: unsafe { NonNull::new_unchecked(Box::into_raw(Box::new(inner))) },
121 _phan: Default::default(),
122 }
123 }
124
125 #[inline(always)]
126 fn get_inner(&self) -> &T {
127 unsafe { self.inner.as_ref() }
128 }
129
130 #[inline]
131 pub fn ptr_eq(this: &Self, other: &Self) -> bool {
132 this.inner == other.inner
133 }
134
135 #[inline]
173 pub fn is_unique(&self) -> bool {
174 self.counter().load(Acquire) == 1u8.into()
178 }
179
180 #[inline]
186 pub fn get_mut(this: &mut Self) -> Option<&mut T> {
187 if this.is_unique() { Some(unsafe { this.inner.as_mut() }) } else { None }
188 }
189}
190
191impl<T: IrcItem<Tag> + Clone, Tag> Irc<T, Tag> {
192 #[inline]
230 pub fn make_mut(this: &mut Self) -> &mut T {
231 if !this.is_unique() {
232 let cloned_item = this.get_inner().clone();
233 let mut new_irc = Self::new(cloned_item);
234 core::mem::swap(this, &mut new_irc);
235 }
236 unsafe { this.inner.as_mut() }
237 }
238}
239
240impl<T: IrcItem<Tag>, Tag> Deref for Irc<T, Tag> {
241 type Target = T;
242 #[inline(always)]
243 fn deref(&self) -> &Self::Target {
244 self.get_inner()
245 }
246}
247
248impl<T: IrcItem<Tag>, Tag> AsRef<T> for Irc<T, Tag> {
249 #[inline(always)]
250 fn as_ref(&self) -> &T {
251 self.get_inner()
252 }
253}
254
255unsafe impl<T: IrcItem<Tag>, Tag> Send for Irc<T, Tag> {}
256unsafe impl<T: IrcItem<Tag>, Tag> Sync for Irc<T, Tag> {}
257
258impl<T: IrcItem<Tag>, Tag> From<Box<T>> for Irc<T, Tag> {
259 #[inline]
263 fn from(inner: Box<T>) -> Self {
264 inner.counter().store(1u8.into(), Relaxed);
265 Self {
266 inner: unsafe { NonNull::new_unchecked(Box::into_raw(inner)) },
267 _phan: Default::default(),
268 }
269 }
270}
271
272impl<T: IrcItem<Tag>, Tag> Clone for Irc<T, Tag> {
273 #[inline]
274 fn clone(&self) -> Self {
275 self.get_inner().counter().fetch_add(1u8.into(), Relaxed);
276 Self { inner: self.inner, _phan: Default::default() }
277 }
278}
279
280impl<T: IrcItem<Tag>, Tag> Drop for Irc<T, Tag> {
281 #[inline]
282 fn drop(&mut self) {
283 let p = self.inner.as_ptr();
284 unsafe {
285 if (*p).counter().fetch_sub(1u8.into(), Release) == 1u8.into() {
286 fence(Acquire);
287 let inner = Box::from_raw(p);
288 IrcItem::<Tag>::on_drop(inner);
289 }
290 }
291 }
292}
293
294impl<T: IrcItem<Tag> + fmt::Debug, Tag> fmt::Debug for Irc<T, Tag> {
295 #[inline]
296 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
297 self.get_inner().fmt(f)
298 }
299}
300
301impl<T: IrcItem<Tag> + fmt::Display, Tag> fmt::Display for Irc<T, Tag> {
302 #[inline]
303 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
304 self.get_inner().fmt(f)
305 }
306}
307
308impl<T: IrcItem<Tag>, Tag> Pointer for Irc<T, Tag> {
309 type Target = T;
310
311 #[inline]
312 fn as_ref(&self) -> &Self::Target {
313 unsafe { self.inner.as_ref() }
314 }
315
316 #[inline]
320 unsafe fn from_raw(p: *const Self::Target) -> Self {
321 Self {
322 inner: unsafe { NonNull::new_unchecked(p as *mut Self::Target) },
323 _phan: Default::default(),
324 }
325 }
326
327 #[inline]
328 fn into_raw(self) -> *const Self::Target {
329 let p = self.inner.as_ptr();
330 core::mem::forget(self);
331 p
332 }
333}
334
335impl<T: IrcItem<Tag>, Tag> SmartPointer for Irc<T, Tag> {
336 #[inline]
337 fn new(inner: T) -> Self {
338 Irc::new(inner)
339 }
340}
341
342#[cfg(test)]
343mod tests {
344 use super::*;
345 use crate::test::{CounterI32, alive_count, reset_alive_count};
346 use core::sync::atomic::AtomicUsize;
347 use std::thread;
348
349 struct Tag;
350
351 struct TestItem {
352 value: CounterI32,
353 counter: AtomicUsize,
354 }
355
356 impl TestItem {
357 fn new(val: i32) -> Self {
358 Self { value: CounterI32::new(val), counter: AtomicUsize::new(0) }
359 }
360 }
361
362 impl Clone for TestItem {
363 fn clone(&self) -> Self {
364 Self { value: self.value.clone(), counter: AtomicUsize::new(0) }
365 }
366 }
367
368 unsafe impl IrcItem<Tag> for TestItem {
369 type Counter = AtomicUsize;
370 fn counter(&self) -> &Self::Counter {
371 &self.counter
372 }
373 }
374
375 #[test]
376 fn test_basic() {
377 reset_alive_count();
378 {
379 let item = TestItem::new(10);
380 let irc1 = Irc::<_, Tag>::new(item);
381 assert_eq!(irc1.value.value, 10);
382 assert_eq!(irc1.strong_count(), 1);
383 assert!(irc1.is_unique());
384 assert_eq!(alive_count(), 1);
385
386 let irc2 = irc1.clone();
387 assert_eq!(irc1.strong_count(), 2);
388 assert_eq!(irc2.strong_count(), 2);
389 assert!(!irc1.is_unique());
390 assert_eq!(alive_count(), 1);
391
392 drop(irc1);
393 assert_eq!(irc2.strong_count(), 1);
394 assert!(irc2.is_unique());
395 assert_eq!(alive_count(), 1);
396 }
397 assert_eq!(alive_count(), 0);
398 }
399
400 #[test]
401 fn test_get_mut() {
402 reset_alive_count();
403 let mut irc = Irc::<_, Tag>::new(TestItem::new(10));
404 assert!(Irc::get_mut(&mut irc).is_some());
405
406 let _irc2 = irc.clone();
407 assert!(Irc::get_mut(&mut irc).is_none());
408 }
409
410 #[test]
411 fn test_make_mut() {
412 reset_alive_count();
413 let mut irc = Irc::<_, Tag>::new(TestItem::new(10));
414
415 {
417 let m = Irc::make_mut(&mut irc);
418 m.value.value = 20;
419 }
420 assert_eq!(irc.value.value, 20);
421 assert_eq!(alive_count(), 1);
422
423 let irc2 = irc.clone();
425 assert_eq!(alive_count(), 1);
426 {
427 let m = Irc::make_mut(&mut irc);
428 m.value.value = 30;
429 }
430 assert_eq!(irc.value.value, 30);
431 assert_eq!(irc2.value.value, 20);
432 assert_eq!(alive_count(), 2);
433
434 assert!(irc.is_unique());
435 assert!(irc2.is_unique());
436 }
437
438 #[test]
439 fn test_multithread_count() {
440 reset_alive_count();
441 {
442 let irc = Irc::<_, Tag>::new(TestItem::new(0));
443 let mut handles = vec![];
444
445 for _ in 0..10 {
446 let irc_clone = irc.clone();
447 handles.push(thread::spawn(move || {
448 for _ in 0..1000 {
449 let temp = irc_clone.clone();
450 assert_eq!(temp.value.value, 0);
451 }
452 }));
453 }
454
455 for handle in handles {
456 handle.join().unwrap();
457 }
458
459 assert_eq!(irc.strong_count(), 1);
460 assert!(irc.is_unique());
461 assert_eq!(alive_count(), 1);
462 }
463 assert_eq!(alive_count(), 0);
464 }
465
466 #[test]
467 fn test_multithread_drop() {
468 reset_alive_count();
469 {
470 let irc = Irc::<_, Tag>::new(TestItem::new(0));
471 let mut handles = vec![];
472 for _ in 0..10 {
473 let irc_clone = irc.clone();
474 handles.push(thread::spawn(move || {
475 for _ in 0..1000 {
476 let temp = irc_clone.clone();
477 assert_eq!(temp.value.value, 0);
478 }
479 }));
480 }
481 drop(irc);
482 for handle in handles {
483 handle.join().unwrap();
484 }
485 }
486 assert_eq!(alive_count(), 0);
487 }
488
489 #[test]
490 fn test_drop_all() {
491 reset_alive_count();
492 let irc = Irc::<_, Tag>::new(TestItem::new(0));
493 let mut clones = vec![];
494 for _ in 0..100 {
495 clones.push(irc.clone());
496 }
497 assert_eq!(alive_count(), 1);
498 drop(clones);
499 assert_eq!(alive_count(), 1);
500 drop(irc);
501 assert_eq!(alive_count(), 0);
502 }
503}