1#![cfg_attr(not(feature = "std"), no_std)]
9
10#[cfg(not(feature = "std"))]
11extern crate alloc;
12
13#[cfg(not(feature = "std"))]
14use alloc::alloc::{alloc, dealloc};
15use core::alloc::Layout;
16use core::marker::Unpin;
17use core::pin::Pin;
18#[cfg(not(feature = "std"))]
19use core::prelude::rust_2018::*;
20use core::ptr::NonNull;
21use core::sync::atomic::{fence, AtomicUsize, Ordering};
22#[cfg(feature = "std")]
23use std::alloc::{alloc, dealloc};
24
25#[repr(transparent)]
27pub struct Handle(BaseArc<()>);
28
29impl<T: ?Sized> From<Arc<T>> for Handle {
30 fn from(arc: Arc<T>) -> Self {
31 Self(unsafe { arc.untranspose::<()>() })
32 }
33}
34
35impl<T: ?Sized> From<BaseArc<T>> for Handle {
36 fn from(arc: BaseArc<T>) -> Self {
37 let data = arc.into_raw();
38 Self(unsafe { BaseArc::from_raw(data as *const ()) })
39 }
40}
41
42#[repr(C)]
43struct ArcHeader {
44 count: AtomicUsize,
45 drop: unsafe extern "C" fn(*mut ()),
46}
47
48pub type DropInPlace = Option<unsafe extern "C" fn(*mut ())>;
49
50#[repr(C)]
51struct DynArcHeader {
52 size: usize,
53 alignment: usize,
54 drop_in_place: DropInPlace,
55 hdr: ArcHeader,
56}
57
58unsafe extern "C" fn do_drop<T>(data: *mut ()) {
59 core::ptr::drop_in_place(data as *mut T);
60 let (header, layout) = layout::<T>();
61 dealloc((data as *mut u8).sub(header), layout);
62}
63
64unsafe extern "C" fn do_drop_in_place<T>(data: *mut ()) {
65 core::ptr::drop_in_place(data as *mut T);
66}
67
68unsafe extern "C" fn do_dyn_drop(data: *mut ()) {
69 let header = (data as *mut DynArcHeader).sub(1);
70 let layout = Layout::from_size_align_unchecked((*header).size, (*header).alignment);
71
72 if let Some(drop_fn) = (*header).drop_in_place {
73 drop_fn(data);
74 }
75
76 dealloc(header as *mut u8, layout);
77}
78
79fn layout<T>() -> (usize, Layout) {
80 header_layout::<DynArcHeader>(unsafe {
81 Layout::from_size_align_unchecked(core::mem::size_of::<T>(), core::mem::align_of::<T>())
82 })
83}
84
85fn header_layout<H>(inp: Layout) -> (usize, Layout) {
86 let alignment = core::cmp::max(inp.align(), core::mem::align_of::<H>());
87 let header_size = core::mem::size_of::<H>();
88
89 let align_up = |val| (val + (alignment - 1)) & !(alignment - 1);
91
92 let header_aligned = align_up(header_size);
93 let size = header_aligned + align_up(inp.size());
94
95 let layout = unsafe { Layout::from_size_align_unchecked(size, alignment) };
97
98 (header_aligned, layout)
99}
100
101unsafe fn allocate<T>() -> NonNull<T> {
102 let (header, layout) = layout::<T>();
103 let data = alloc(layout).add(header);
104
105 assert!(!data.is_null());
106
107 NonNull::new_unchecked(data as *mut T)
108}
109
110unsafe fn initialize<T>(data: NonNull<T>, val: T) {
111 let header = (data.as_ptr() as *mut ArcHeader).sub(1);
112 header.write(ArcHeader {
113 count: AtomicUsize::new(1),
114 drop: do_drop::<T>,
115 });
116 data.as_ptr().write(val);
117}
118
119#[repr(transparent)]
133pub struct BaseArc<T: ?Sized> {
134 data: NonNull<T>,
135}
136
137impl BaseArc<()> {
138 pub unsafe fn custom(layout: Layout, drop_in_place: DropInPlace) -> Self {
160 let (header, layout) = header_layout::<DynArcHeader>(layout);
161 let data = alloc(layout);
162
163 assert!(!data.is_null());
164
165 let hdr = data as *mut DynArcHeader;
166
167 hdr.write(DynArcHeader {
168 size: layout.size(),
169 alignment: layout.align(),
170 drop_in_place,
171 hdr: ArcHeader {
172 count: AtomicUsize::new(1),
173 drop: do_dyn_drop,
174 },
175 });
176
177 let data = NonNull::new_unchecked(data.add(header) as *mut _);
178
179 Self { data }
180 }
181}
182
183impl<T> BaseArc<T> {
184 pub fn new(val: T) -> Self {
185 let data = unsafe { allocate::<T>() };
186 unsafe {
187 initialize::<T>(data, val);
188 }
189
190 Self { data }
191 }
192
193 pub fn pin(data: T) -> Pin<Self> {
194 unsafe { Pin::new_unchecked(Self::new(data)) }
195 }
196
197 pub fn transpose<O>(self) -> Arc<O>
198 where
199 T: AsRef<O>,
200 {
201 assert!(core::mem::size_of::<O>() <= core::mem::size_of::<T>());
203
204 let transposed = (*self).as_ref() as *const _ as *const u8;
205 let raw = self.into_raw() as *const u8;
206
207 unsafe {
208 let off = (transposed as usize).checked_sub(raw as usize).unwrap();
209
210 assert!(off <= (core::mem::size_of::<T>() - core::mem::size_of::<O>()));
212
213 Arc::from_raw(raw.add(off) as *const O, off)
214 }
215 }
216}
217
218impl<T: ?Sized> BaseArc<T> {
219 fn header(&self) -> &ArcHeader {
220 unsafe { &*((self.data.as_ptr() as *mut u8) as *mut ArcHeader).sub(1) }
221 }
222
223 pub unsafe fn from_raw(data: *const T) -> Self {
229 Self {
230 data: NonNull::new_unchecked(data as *mut _),
231 }
232 }
233
234 pub fn into_raw(self) -> *const T {
235 let ret = self.data.as_ptr() as *const _;
236 core::mem::forget(self);
237 ret
238 }
239
240 pub unsafe fn increment_strong_count(ptr: *const T) {
249 let arc = core::mem::ManuallyDrop::new(Self::from_raw(ptr));
251 let _arc_clone: core::mem::ManuallyDrop<_> = arc.clone();
253 }
254
255 pub unsafe fn decrement_strong_count(ptr: *const T) {
264 core::mem::drop(BaseArc::from_raw(ptr));
265 }
266
267 unsafe fn as_original_ptr<O: Sized>(&self) -> *const O {
269 (self.data.as_ptr() as *const u8) as *const O
270 }
271}
272
273#[repr(C)]
287pub struct Arc<T: ?Sized> {
288 data: NonNull<T>,
289 offset: usize,
290}
291
292impl<T> Arc<T> {
293 pub fn new(val: T) -> Self {
294 let data = unsafe { allocate::<T>() };
295 unsafe {
296 initialize::<T>(data, val);
297 }
298
299 Self { data, offset: 0 }
300 }
301
302 pub fn pin(data: T) -> Pin<Self> {
303 unsafe { Pin::new_unchecked(Self::new(data)) }
304 }
305
306 pub fn transpose<O>(self) -> Arc<O>
307 where
308 T: AsRef<O>,
309 {
310 assert!(core::mem::size_of::<O>() <= core::mem::size_of::<T>());
312
313 let transposed = (*self).as_ref() as *const _ as *const u8;
314 let (raw, offset) = self.into_raw();
315 let raw = raw as *const u8;
316
317 unsafe {
318 let off = (transposed as usize).checked_sub(raw as usize).unwrap();
319
320 assert!(off <= (core::mem::size_of::<T>() - core::mem::size_of::<O>()));
322
323 Arc::from_raw(raw.add(off) as *const O, offset + off)
324 }
325 }
326}
327
328impl<T: ?Sized> Arc<T> {
329 fn header(&self) -> &ArcHeader {
330 unsafe { &*((self.data.as_ptr() as *mut u8).sub(self.offset) as *mut ArcHeader).sub(1) }
331 }
332
333 pub unsafe fn from_raw(data: *const T, offset: usize) -> Self {
341 Self {
342 data: NonNull::new_unchecked(data as *mut _),
343 offset,
344 }
345 }
346
347 pub fn into_raw(self) -> (*const T, usize) {
348 let ret = self.data.as_ptr() as *const _;
349 let offset = self.offset;
350 core::mem::forget(self);
351 (ret, offset)
352 }
353
354 pub unsafe fn increment_strong_count(ptr: *const T, offset: usize) {
365 let arc = core::mem::ManuallyDrop::new(Self::from_raw(ptr, offset));
367 let _arc_clone: core::mem::ManuallyDrop<_> = arc.clone();
369 }
370
371 pub unsafe fn decrement_strong_count(ptr: *const T, offset: usize) {
384 core::mem::drop(Arc::from_raw(ptr, offset));
385 }
386
387 pub unsafe fn untranspose<O>(self) -> BaseArc<O> {
393 let (raw, offset) = self.into_raw();
394 let raw = (raw as *const u8).sub(offset) as *const O;
395 BaseArc::from_raw(raw)
396 }
397
398 pub unsafe fn as_original_ptr<O>(&self) -> *const O {
404 (self.data.as_ptr() as *const u8).sub(self.offset) as *const O
405 }
406
407 pub fn is_original(&self) -> bool {
408 self.offset == 0
409 }
410
411 pub fn into_base(self) -> Result<BaseArc<T>, Self> {
412 if self.offset == 0 {
413 let (raw, _) = self.into_raw();
414 Ok(unsafe { BaseArc::from_raw(raw) })
415 } else {
416 Err(self)
417 }
418 }
419}
420
421macro_rules! doc {
426 ( $(#[doc = $expr1:expr])* ### #[doc = $expr2:expr] $($tt:tt)* ) => {
427 doc! {
428 $(#[doc = $expr1])*
429 #[doc = $expr2]
430 ###
431 $($tt)*
432 }
433 };
434 ( $(#[doc = $exprs:expr])* ### $($tt:tt)* ) => {
435 $(#[doc = $exprs])*
436 $($tt)*
437 };
438 ( $($tt:tt)* ) => {
439 doc! {
440 ###
441 $($tt)*
442 }
443 }
444}
445
446macro_rules! arc_traits {
447 ($mname:ident, $ty:ident) => {
448
449 impl<T> $ty<T> {
450 pub fn strong_count(&self) -> usize {
451 self.header().count.load(Ordering::Acquire)
452 }
453
454 pub fn as_ptr(&self) -> *const T {
455 self.data.as_ptr() as *const _
456 }
457
458 pub fn exclusive_ptr(&self) -> Option<NonNull<T>> {
459 if self.strong_count() == 1 {
460 Some(self.data)
461 } else {
462 None
463 }
464 }
465
466 pub fn get_mut(&mut self) -> Option<&mut T> {
467 self.exclusive_ptr().map(|v| unsafe { &mut *v.as_ptr() })
468 }
469 }
470
471 mod $mname {
472 use super::*;
473 impl<T: Default> Default for $ty<T> {
474 doc! {
475 #[doc = concat!("Creates a new `", stringify!($ty), "<T>`, with the `Default` value for `T`.")]
476 #[doc = concat!("use tarc::", stringify!($ty), ";")]
481 #[doc = concat!("let x: ", stringify!($ty), "<i32> = Default::default();")]
483 fn default() -> Self {
486 Self::new(T::default())
487 }
488 }
489 }
490
491 impl<T: ?Sized> core::ops::Deref for $ty<T> {
492 type Target = T;
493
494 fn deref(&self) -> &Self::Target {
495 unsafe { self.data.as_ref() }
496 }
497 }
498
499 impl<T: ?Sized + core::hash::Hash> core::hash::Hash for $ty<T> {
500 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
501 (**self).hash(state)
502 }
503 }
504
505 impl<T: ?Sized> Unpin for $ty<T> {}
506
507 unsafe impl<T: ?Sized + Sync + Send> Send for $ty<T> {}
508 unsafe impl<T: ?Sized + Sync + Send> Sync for $ty<T> {}
509
510 doc! {
511 #[doc = concat!("Converts a `T` into an `", stringify!($ty), "<T>`")]
512 #[doc = concat!("newly allocated `", stringify!($ty), "`. It is equivalent to")]
515 #[doc = concat!(" calling `", stringify!($ty), "::new(t)`")]
516 #[doc = concat!("# use tarc:: ", stringify!($ty), ";")]
520 #[doc = concat!("let arc = ", stringify!($ty), "::new(5);")]
522 #[doc = concat!("assert_eq!(", stringify!($ty), "::from(x), arc);")]
524 impl<T> From<T> for $ty<T> {
526 fn from(t: T) -> Self {
527 Self::new(t)
528 }
529 }
530 }
531
532 impl<T: ?Sized> Clone for $ty<T> {
533 doc! {
534 #[doc = concat!("Makes a clone of the `", stringify!($ty), "` pointer.")]
535 #[doc = concat!("use tarc::", stringify!($ty), ";")]
543 #[doc = concat!("let five = ", stringify!($ty), "::new(5);")]
545 #[doc = concat!("let _ = ", stringify!($ty), "::clone(&five);")]
547 fn clone(&self) -> Self {
549 if self.header().count.fetch_add(1, Ordering::Relaxed) > core::isize::MAX as usize {
550 panic!()
551 }
552
553 Self { ..*self }
554 }
555 }
556 }
557
558 impl<T: ?Sized> Drop for $ty<T> {
559 doc! {
560 #[doc = concat!("Drops the `", stringify!($ty), "`.")]
561 #[doc = concat!("use tarc::", stringify!($ty), ";")]
569 #[doc = concat!("let foo = ", stringify!($ty), "::new(Foo);")]
579 #[doc = concat!("let foo2 = ", stringify!($ty), "::clone(&foo);")]
580 fn drop(&mut self) {
585 let header = self.header();
586
587 if header.count.fetch_sub(1, Ordering::Release) != 1 {
588 return;
589 }
590
591 fence(Ordering::SeqCst);
592
593 unsafe { (header.drop)(self.as_original_ptr::<()>() as *mut ()) }
594 }
595 }
596 }
597
598 impl<T: ?Sized + PartialEq> PartialEq for $ty<T> {
599 doc! {
600 #[doc = concat!("Equality for two `", stringify!($ty), "`s.")]
601 #[doc = concat!("Two `", stringify!($ty), "`s are equal if their inner values are equal, even if they are")]
603 #[doc = concat!("two `", stringify!($ty), "`s that point to the same allocation are always equal.")]
607 #[doc = concat!("use tarc::", stringify!($ty), ";")]
612 #[doc = concat!("let five = ", stringify!($ty), "::new(5);")]
614 #[doc = concat!("assert!(five == ", stringify!($ty), "::new(5));")]
616 #[inline]
618 fn eq(&self, other: &$ty<T>) -> bool {
619 (**self == **other)
621 }
622 }
623
624 doc! {
625 #[doc = concat!("Inequality for two `", stringify!($ty), "`s.")]
626 #[doc = concat!("Two `", stringify!($ty), "`s are unequal if their inner values are unequal.")]
628 #[doc = concat!("two `", stringify!($ty), "`s that point to the same value are never unequal.")]
631 #[doc = concat!("use tarc::", stringify!($ty), ";")]
636 #[doc = concat!("let five = ", stringify!($ty), "::new(5);")]
638 #[doc = concat!("assert!(five != ", stringify!($ty), "::new(6));")]
640 #[inline]
642 #[allow(clippy::partialeq_ne_impl)]
643 fn ne(&self, other: &$ty<T>) -> bool {
644 (**self != **other)
646 }
647 }
648 }
649
650 use core::cmp::{Ord, Ordering as CmpOrdering};
651
652 impl<T: ?Sized + PartialOrd> PartialOrd for $ty<T> {
653 doc! {
654 #[doc = concat!("Partial comparison for two `", stringify!($ty), "`s.")]
655 #[doc = concat!("use tarc::", stringify!($ty), ";")]
662 #[doc = concat!("let five = ", stringify!($ty), "::new(5);")]
665 #[doc = concat!("assert_eq!(Some(Ordering::Less), five.partial_cmp(&", stringify!($ty), "::new(6)));")]
667 fn partial_cmp(&self, other: &$ty<T>) -> Option<CmpOrdering> {
669 (**self).partial_cmp(&**other)
670 }
671 }
672
673 doc! {
674 #[doc = concat!("Less-than comparison for two `", stringify!($ty), "`s.")]
675 #[doc = concat!("use tarc::", stringify!($ty), ";")]
682 #[doc = concat!("let five = ", stringify!($ty), "::new(5);")]
684 #[doc = concat!("assert!(five < ", stringify!($ty), "::new(6));")]
686 fn lt(&self, other: &$ty<T>) -> bool {
688 *(*self) < *(*other)
689 }
690 }
691
692 doc! {
693 #[doc = concat!("'Less than or equal to' comparison for two `", stringify!($ty), "`s.")]
694 #[doc = concat!("use tarc::", stringify!($ty), ";")]
701 #[doc = concat!("let five = ", stringify!($ty), "::new(5);")]
703 #[doc = concat!("assert!(five <= ", stringify!($ty), "::new(5));")]
705 fn le(&self, other: &$ty<T>) -> bool {
707 *(*self) <= *(*other)
708 }
709 }
710
711 doc! {
712 #[doc = concat!("Greater-than comparison for two `", stringify!($ty), "`s.")]
713 #[doc = concat!("use tarc::", stringify!($ty), ";")]
720 #[doc = concat!("let five = ", stringify!($ty), "::new(5);")]
722 #[doc = concat!("assert!(five > ", stringify!($ty), "::new(4));")]
724 fn gt(&self, other: &$ty<T>) -> bool {
726 *(*self) > *(*other)
727 }
728 }
729
730 doc! {
731 #[doc = concat!("'Greater than or equal to' comparison for two `", stringify!($ty), "`s.")]
732 #[doc = concat!("use tarc::", stringify!($ty), ";")]
739 #[doc = concat!("let five = ", stringify!($ty), "::new(5);")]
741 #[doc = concat!("assert!(five >= ", stringify!($ty), "::new(5));")]
743 fn ge(&self, other: &$ty<T>) -> bool {
745 *(*self) >= *(*other)
746 }
747 }
748 }
749
750 impl<T: ?Sized + Eq> Eq for $ty<T> {}
751
752 impl<T: ?Sized + Ord> Ord for $ty<T> {
753 doc! {
754 #[doc = concat!("Comparison for two `", stringify!($ty), "`s.")]
755 #[doc = concat!("use tarc::", stringify!($ty), ";")]
762 #[doc = concat!("let five = ", stringify!($ty), "::new(5);")]
765 #[doc = concat!("assert_eq!(Ordering::Less, five.cmp(& ", stringify!($ty), "::new(6)));")]
767 fn cmp(&self, other: &$ty<T>) -> CmpOrdering {
769 (**self).cmp(&**other)
770 }
771 }
772 }
773
774 use core::fmt;
775
776 impl<T: ?Sized + fmt::Display> fmt::Display for $ty<T> {
777 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
778 fmt::Display::fmt(&**self, f)
779 }
780 }
781
782 impl<T: ?Sized + fmt::Debug> fmt::Debug for $ty<T> {
783 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
784 fmt::Debug::fmt(&**self, f)
785 }
786 }
787
788 impl<T: ?Sized> fmt::Pointer for $ty<T> {
789 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
790 fmt::Pointer::fmt(&(&**self as *const T), f)
791 }
792 }
793
794 impl<T: ?Sized> core::borrow::Borrow<T> for $ty<T> {
795 fn borrow(&self) -> &T {
796 &**self
797 }
798 }
799
800 impl<T: ?Sized> AsRef<T> for $ty<T> {
801 fn as_ref(&self) -> &T {
802 &**self
803 }
804 }
805
806 #[cfg(feature = "std")]
807 mod std_impl {
808 use super::*;
809 use std::error::Error;
810
811 impl<T: Error + ?Sized> Error for $ty<T> {
812 #[allow(deprecated, deprecated_in_future)]
813 fn description(&self) -> &str {
814 Error::description(&**self)
815 }
816
817 #[allow(deprecated)]
818 fn cause(&self) -> Option<&dyn Error> {
819 Error::cause(&**self)
820 }
821
822 fn source(&self) -> Option<&(dyn Error + 'static)> {
823 Error::source(&**self)
824 }
825 }
826 }
827 }
828 };
829}
830
831arc_traits!(base_arc, BaseArc);
832arc_traits!(arc, Arc);