1use crate::{Pointer, SmartPointer};
85use alloc::boxed::Box;
86use atomic_traits::{
87 Atomic, NumOps,
88 fetch::{Add, Sub},
89};
90use core::fmt;
91use core::marker::PhantomData;
92use core::ops::Deref;
93use core::ptr::NonNull;
94use core::sync::atomic::{
95 Ordering::{Acquire, Relaxed, Release},
96 fence,
97};
98
99pub unsafe trait IrcItem<Tag = (), P = Box<Self>>: Sized + Send + Sync
107where
108 <Self::Counter as Atomic>::Type: From<u8> + Into<usize> + PartialEq,
109 P: Pointer<Target = Self>,
110{
111 type Counter: NumOps;
113
114 fn counter(&self) -> &Self::Counter;
116
117 #[inline(always)]
121 fn on_drop(_this: P) {}
122
123 #[inline]
124 fn strong_count(&self) -> usize {
125 self.counter().load(Relaxed).into()
126 }
127}
128
129pub struct Irc<T, Tag = (), P = Box<T>>
133where
134 T: IrcItem<Tag, P>,
135 P: Pointer<Target = T>,
136{
137 inner: NonNull<T>,
138 _phan: PhantomData<fn(&Tag, &P)>,
139}
140
141impl<T, Tag, P> Irc<T, Tag, P>
142where
143 T: IrcItem<Tag, P>,
144 P: SmartPointer<Target = T>,
145{
146 #[inline]
150 pub fn new(inner: T) -> Self {
151 Self::from(P::new(inner))
152 }
153}
154
155impl<T: IrcItem<Tag, P>, Tag, P> SmartPointer for Irc<T, Tag, P>
156where
157 T: IrcItem<Tag, P>,
158 P: SmartPointer<Target = T>,
159{
160 #[inline]
161 fn new(inner: T) -> Self {
162 Irc::new(inner)
163 }
164}
165
166impl<T, Tag, P> From<P> for Irc<T, Tag, P>
167where
168 T: IrcItem<Tag, P>,
169 P: Pointer<Target = T>,
170{
171 #[inline]
175 fn from(inner: P) -> Self {
176 inner.as_ref().counter().store(1u8.into(), Relaxed);
177 Self {
178 inner: unsafe { NonNull::new_unchecked(inner.into_raw() as *mut T) },
179 _phan: Default::default(),
180 }
181 }
182}
183
184impl<T, Tag, P> Irc<T, Tag, P>
185where
186 T: IrcItem<Tag, P>,
187 P: Pointer<Target = T>,
188{
189 #[inline(always)]
190 fn get_inner(&self) -> &T {
191 unsafe { self.inner.as_ref() }
192 }
193
194 #[inline]
195 pub fn ptr_eq(this: &Self, other: &Self) -> bool {
196 this.inner == other.inner
197 }
198
199 #[inline]
205 pub unsafe fn with_unchecked(inner: P) -> Self {
206 inner.as_ref().counter().fetch_add(1u8.into(), Relaxed);
207 Self {
208 inner: unsafe { NonNull::new_unchecked(inner.into_raw() as *mut T) },
209 _phan: Default::default(),
210 }
211 }
212
213 #[inline]
252 pub fn is_unique(&self) -> bool {
253 self.counter().load(Acquire) == 1u8.into()
257 }
258
259 #[inline]
265 pub fn get_mut(this: &mut Self) -> Option<&mut T> {
266 if this.is_unique() { Some(unsafe { this.inner.as_mut() }) } else { None }
267 }
268}
269
270impl<T, Tag, P> Irc<T, Tag, P>
271where
272 T: IrcItem<Tag, P> + Clone,
273 P: SmartPointer<Target = T>,
274{
275 #[inline]
313 pub fn make_mut(this: &mut Self) -> &mut T {
314 if !this.is_unique() {
315 let cloned_item = this.get_inner().clone();
316 let mut new_irc = Self::new(cloned_item);
317 core::mem::swap(this, &mut new_irc);
318 }
319 unsafe { this.inner.as_mut() }
320 }
321}
322
323impl<T, Tag, P> Deref for Irc<T, Tag, P>
324where
325 T: IrcItem<Tag, P>,
326 P: Pointer<Target = T>,
327{
328 type Target = T;
329 #[inline(always)]
330 fn deref(&self) -> &Self::Target {
331 self.get_inner()
332 }
333}
334
335impl<T, Tag, P> AsRef<T> for Irc<T, Tag, P>
336where
337 T: IrcItem<Tag, P>,
338 P: Pointer<Target = T>,
339{
340 #[inline(always)]
341 fn as_ref(&self) -> &T {
342 self.get_inner()
343 }
344}
345
346unsafe impl<T, Tag, P> Send for Irc<T, Tag, P>
347where
348 T: IrcItem<Tag, P>,
349 P: Pointer<Target = T>,
350{
351}
352unsafe impl<T, Tag, P> Sync for Irc<T, Tag, P>
353where
354 T: IrcItem<Tag, P>,
355 P: Pointer<Target = T>,
356{
357}
358
359impl<T, Tag, P> Clone for Irc<T, Tag, P>
360where
361 T: IrcItem<Tag, P>,
362 P: Pointer<Target = T>,
363{
364 #[inline]
365 fn clone(&self) -> Self {
366 self.get_inner().counter().fetch_add(1u8.into(), Relaxed);
367 Self { inner: self.inner, _phan: Default::default() }
368 }
369}
370
371impl<T, Tag, P> Drop for Irc<T, Tag, P>
372where
373 T: IrcItem<Tag, P>,
374 P: Pointer<Target = T>,
375{
376 #[inline]
377 fn drop(&mut self) {
378 let p = self.inner.as_ptr();
379 unsafe {
380 if (*p).counter().fetch_sub(1u8.into(), Release) == 1u8.into() {
381 fence(Acquire);
382 let inner = P::from_raw(p);
383 IrcItem::<Tag, P>::on_drop(inner);
384 }
385 }
386 }
387}
388
389impl<T, Tag, P> fmt::Debug for Irc<T, Tag, P>
390where
391 T: IrcItem<Tag, P> + fmt::Debug,
392 P: Pointer<Target = T>,
393{
394 #[inline]
395 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
396 self.get_inner().fmt(f)
397 }
398}
399
400impl<T, Tag, P> fmt::Display for Irc<T, Tag, P>
401where
402 T: IrcItem<Tag, P> + fmt::Display,
403 P: Pointer<Target = T>,
404{
405 #[inline]
406 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
407 self.get_inner().fmt(f)
408 }
409}
410
411impl<T: IrcItem<Tag, P>, Tag, P> Pointer for Irc<T, Tag, P>
412where
413 T: IrcItem<Tag, P>,
414 P: Pointer<Target = T>,
415{
416 type Target = T;
417
418 #[inline]
419 fn as_ref(&self) -> &Self::Target {
420 unsafe { self.inner.as_ref() }
421 }
422
423 #[inline]
427 unsafe fn from_raw(p: *const Self::Target) -> Self {
428 Self {
429 inner: unsafe { NonNull::new_unchecked(p as *mut Self::Target) },
430 _phan: Default::default(),
431 }
432 }
433
434 #[inline]
435 fn into_raw(self) -> *const Self::Target {
436 let p = self.inner.as_ptr();
437 core::mem::forget(self);
438 p
439 }
440}
441
442#[cfg(test)]
443mod tests {
444 use super::*;
445 use crate::test::{CounterI32, alive_count, reset_alive_count};
446 use alloc::sync::Arc;
447 use core::sync::atomic::AtomicUsize;
448 use std::thread;
449
450 struct TestItem {
451 value: CounterI32,
452 counter: AtomicUsize,
453 }
454
455 impl TestItem {
456 fn new(val: i32) -> Self {
457 Self { value: CounterI32::new(val), counter: AtomicUsize::new(0) }
458 }
459 }
460
461 impl Clone for TestItem {
462 fn clone(&self) -> Self {
463 Self { value: self.value.clone(), counter: AtomicUsize::new(0) }
464 }
465 }
466
467 unsafe impl IrcItem for TestItem {
468 type Counter = AtomicUsize;
469 fn counter(&self) -> &Self::Counter {
470 &self.counter
471 }
472 }
473
474 struct ArcTestItem {
475 value: CounterI32,
476 counter: AtomicUsize,
477 }
478
479 impl ArcTestItem {
480 fn new(val: i32) -> Self {
481 Self { value: CounterI32::new(val), counter: AtomicUsize::new(0) }
482 }
483 }
484
485 unsafe impl IrcItem<(), Arc<ArcTestItem>> for ArcTestItem {
486 type Counter = AtomicUsize;
487 fn counter(&self) -> &Self::Counter {
488 &self.counter
489 }
490 }
491
492 #[test]
493 fn test_basic() {
494 reset_alive_count();
495 {
496 let item = TestItem::new(10);
497 let irc1 = Irc::<_, _, _>::new(item);
498 assert_eq!(irc1.value.value, 10);
499 assert_eq!(irc1.strong_count(), 1);
500 assert!(irc1.is_unique());
501 assert_eq!(alive_count(), 1);
502
503 let irc2 = irc1.clone();
504 assert_eq!(irc1.strong_count(), 2);
505 assert_eq!(irc2.strong_count(), 2);
506 assert!(!irc1.is_unique());
507 assert_eq!(alive_count(), 1);
508
509 drop(irc1);
510 assert_eq!(irc2.strong_count(), 1);
511 assert!(irc2.is_unique());
512 assert_eq!(alive_count(), 1);
513 }
514 assert_eq!(alive_count(), 0);
515 }
516
517 #[test]
518 fn test_arc_underlayer() {
519 reset_alive_count();
520 {
521 let item = ArcTestItem::new(10);
522 let irc1 = Irc::<ArcTestItem, (), Arc<ArcTestItem>>::new(item);
523 assert_eq!(irc1.value.value, 10);
524 assert_eq!(irc1.strong_count(), 1);
525 assert!(irc1.is_unique());
526 assert_eq!(alive_count(), 1);
527
528 let irc2 = irc1.clone();
529 assert_eq!(irc1.strong_count(), 2);
530 assert_eq!(alive_count(), 1);
531
532 drop(irc1);
533 assert_eq!(irc2.strong_count(), 1);
534 assert_eq!(alive_count(), 1);
535 }
536 assert_eq!(alive_count(), 0);
537 }
538
539 #[test]
540 fn test_get_mut() {
541 reset_alive_count();
542 let mut irc = Irc::<_, _, _>::new(TestItem::new(10));
543 assert!(Irc::get_mut(&mut irc).is_some());
544
545 let _irc2 = irc.clone();
546 assert!(Irc::get_mut(&mut irc).is_none());
547 }
548
549 #[test]
550 fn test_make_mut() {
551 reset_alive_count();
552 let mut irc = Irc::new(TestItem::new(10));
553
554 {
556 let m = Irc::make_mut(&mut irc);
557 m.value.value = 20;
558 }
559 assert_eq!(irc.value.value, 20);
560 assert_eq!(alive_count(), 1);
561
562 let irc2 = irc.clone();
564 assert_eq!(alive_count(), 1);
565 {
566 let m = Irc::make_mut(&mut irc);
567 m.value.value = 30;
568 }
569 assert_eq!(irc.value.value, 30);
570 assert_eq!(irc2.value.value, 20);
571 assert_eq!(alive_count(), 2);
572
573 assert!(irc.is_unique());
574 assert!(irc2.is_unique());
575 }
576
577 #[test]
578 fn test_multithread_count() {
579 reset_alive_count();
580 {
581 let irc = Irc::new(TestItem::new(0));
582 let mut handles = vec![];
583
584 for _ in 0..10 {
585 let irc_clone = irc.clone();
586 handles.push(thread::spawn(move || {
587 for _ in 0..1000 {
588 let temp = irc_clone.clone();
589 assert_eq!(temp.value.value, 0);
590 }
591 }));
592 }
593
594 for handle in handles {
595 handle.join().unwrap();
596 }
597
598 assert_eq!(irc.strong_count(), 1);
599 assert!(irc.is_unique());
600 assert_eq!(alive_count(), 1);
601 }
602 assert_eq!(alive_count(), 0);
603 }
604
605 #[test]
606 fn test_multithread_drop() {
607 reset_alive_count();
608 {
609 let irc = Irc::new(TestItem::new(0));
610 let mut handles = vec![];
611 for _ in 0..10 {
612 let irc_clone = irc.clone();
613 handles.push(thread::spawn(move || {
614 for _ in 0..1000 {
615 let temp = irc_clone.clone();
616 assert_eq!(temp.value.value, 0);
617 }
618 }));
619 }
620 drop(irc);
621 for handle in handles {
622 handle.join().unwrap();
623 }
624 }
625 assert_eq!(alive_count(), 0);
626 }
627
628 #[test]
629 fn test_drop_all() {
630 reset_alive_count();
631 let irc = Irc::new(TestItem::new(0));
632 let mut clones = vec![];
633 for _ in 0..100 {
634 clones.push(irc.clone());
635 }
636 assert_eq!(alive_count(), 1);
637 drop(clones);
638 assert_eq!(alive_count(), 1);
639 drop(irc);
640 assert_eq!(alive_count(), 0);
641 }
642
643 #[test]
644 fn test_from_into_raw() {
645 {
646 let irc = Irc::new(TestItem::new(0));
647 let irc_1 = irc.clone();
648 let irc_2 = irc.clone();
649 let irc1_p = irc_1.into_raw();
650 let irc2_p = irc_2.into_raw();
651 assert_eq!(irc.strong_count(), 3);
652 assert_eq!(alive_count(), 1);
653 let _irc1 = unsafe { Irc::from_raw(irc1_p) };
654 let _irc2 = unsafe { Irc::from_raw(irc2_p) };
655 assert_eq!(irc.strong_count(), 3);
656 assert_eq!(alive_count(), 1);
657 }
658 assert_eq!(alive_count(), 0);
659 }
660}