1use std::{
2 alloc::Layout,
3 ptr::NonNull,
4 sync::{
5 Arc,
6 atomic::{
7 AtomicUsize,
8 Ordering,
9 },
10 },
11};
12
13use crate::{
14 ops::place::{
15 BorrowPlace,
16 CreateHandle,
17 PlaceHandle,
18 PlaceProxy,
19 borrowck::{
20 AccessKind,
21 Instant,
22 Lifetime,
23 },
24 },
25 sync::arc_ref::ArcRef,
26};
27
28#[repr(C, align(2))]
29struct ArcInner<T: ?Sized> {
30 strong: AtomicUsize,
31 weak: AtomicUsize,
32 data: T,
33}
34
35#[repr(C, align(2))]
36pub(super) struct ArcHead {
37 pub(super) strong: AtomicUsize,
38 pub(super) weak: AtomicUsize,
39}
40
41pub struct ArcHandle<T: ?Sized>(NonNull<ArcInner<T>>);
42
43impl<T: ?Sized> PlaceProxy for Arc<T> {
44 type Target = T;
45}
46
47unsafe impl<T: ?Sized> CreateHandle<Instant> for Arc<T> {
48 type Handle = ArcHandle<T>;
49
50 const ACCESS: AccessKind = AccessKind::Shared;
51
52 unsafe fn handle_from_raw(this: *const Self) -> Self::Handle {
53 let ptr: *const NonNull<ArcInner<T>> = this.cast();
54 let ptr: NonNull<ArcInner<T>> = unsafe { ptr.read() };
55 ArcHandle(ptr)
56 }
57}
58
59impl<T: ?Sized> PlaceHandle for ArcHandle<T> {
60 type Target = T;
61}
62
63unsafe impl<'a, T: ?Sized> BorrowPlace<&'a T> for ArcHandle<T> {
64 const ACCESS: AccessKind = AccessKind::Shared;
65 type Timing = Lifetime<'a>;
66 const SAFE: bool = true;
67
68 unsafe fn borrow(self) -> &'a T {
69 let ptr = self.0.as_ptr();
70 unsafe { &(*ptr).data }
71 }
72}
73
74unsafe impl<T: ?Sized> BorrowPlace<*const T> for ArcHandle<T> {
75 const ACCESS: AccessKind = AccessKind::Shared;
76 type Timing = Instant;
77 const SAFE: bool = true;
78
79 unsafe fn borrow(self) -> *const T {
80 let ptr = self.0.as_ptr();
81 unsafe { &raw const (*ptr).data }
82 }
83}
84
85unsafe impl<T: ?Sized> BorrowPlace<NonNull<T>> for ArcHandle<T> {
86 const ACCESS: AccessKind = AccessKind::Shared;
87 type Timing = Instant;
88 const SAFE: bool = true;
89
90 unsafe fn borrow(self) -> NonNull<T> {
91 let ptr = self.0.as_ptr();
92 unsafe { NonNull::new_unchecked(&raw mut (*ptr).data) }
93 }
94}
95
96unsafe impl<T: ?Sized> BorrowPlace<ArcRef<T>> for ArcHandle<T> {
97 const ACCESS: AccessKind = AccessKind::Shared;
98 type Timing = Instant;
99 const SAFE: bool = true;
100
101 unsafe fn borrow(self) -> ArcRef<T> {
102 let data: *mut ArcInner<T> = self.0.as_ptr();
103 let data: *mut T = unsafe { &raw mut (*data).data };
104 let layout = unsafe { Layout::for_value_raw(data) };
105 let data = unsafe { NonNull::new_unchecked(data) };
106 let head: NonNull<ArcHead> = self.0.cast();
107 unsafe {
108 let strong = &(*head.as_ptr()).strong;
109 let old = strong.fetch_add(1, Ordering::Relaxed);
110 {
match (&old, &0) {
(left_val, right_val) => {
if *left_val == *right_val {
let kind = ::core::panicking::AssertKind::Ne;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};assert_ne!(old, 0);
111 }
112 ArcRef { head, layout, data }
113 }
114}