osom_lib_arc/carc_array/
carc_array.rs1use core::cmp::Ordering as CmpOrdering;
2use core::{
3 borrow::Borrow,
4 ops::Deref,
5 sync::atomic::{Ordering, fence},
6};
7
8use osom_lib_alloc::traits::Allocator;
9use osom_lib_primitives::length::Length;
10use osom_lib_reprc::traits::ReprC;
11use osom_lib_try_clone::TryClone;
12
13use crate::{
14 carc_array::{CWeakArray, internal::InternalArcArray},
15 consts::MAX_REFERENCES,
16 errors::MaxReferencesExceededError,
17};
18
19#[repr(transparent)]
24#[must_use]
25#[derive(Debug)]
26pub struct CArcArray<T, TAllocator: Allocator> {
27 internal: InternalArcArray<T, TAllocator>,
28}
29
30unsafe impl<T: ReprC, TAllocator: Allocator> ReprC for CArcArray<T, TAllocator> {
31 const CHECK: () = const {
32 osom_lib_reprc::hidden::is_reprc::<T>();
33 osom_lib_reprc::hidden::is_reprc::<CWeakArray<T, TAllocator>>();
34 osom_lib_reprc::hidden::is_reprc::<InternalArcArray<T, TAllocator>>();
35 };
36}
37
38impl<T, TAllocator: Allocator> CArcArray<T, TAllocator> {
39 #[inline]
40 pub(super) const fn from_internal(internal: InternalArcArray<T, TAllocator>) -> Self {
41 Self { internal }
42 }
43
44 #[inline(always)]
46 #[must_use]
47 pub fn strong_count(carc: &Self) -> u32 {
48 carc.internal.strong().load(Ordering::Relaxed)
49 }
50
51 #[inline(always)]
53 #[must_use]
54 pub fn weak_count(carc: &Self) -> u32 {
55 carc.internal.weak().load(Ordering::Relaxed)
56 }
57
58 #[inline]
60 #[must_use]
61 pub const fn data(carc: &Self) -> &[T] {
62 carc.internal.data_slice()
63 }
64
65 #[inline]
67 pub const fn length(carc: &Self) -> Length {
68 carc.internal.size()
69 }
70
71 pub fn downgrade(carc: &Self) -> Result<CWeakArray<T, TAllocator>, MaxReferencesExceededError> {
77 let internal_clone = carc.internal.raw_clone();
78 let prev_value = internal_clone.weak().fetch_add(1, Ordering::Relaxed);
79 if prev_value >= MAX_REFERENCES {
80 internal_clone.weak().fetch_sub(1, Ordering::Relaxed);
81 return Err(MaxReferencesExceededError);
82 }
83 Ok(CWeakArray::from_internal(internal_clone))
84 }
85
86 #[inline]
92 #[must_use]
93 pub fn abandon(mut carc: Self) -> Option<CWeakArray<T, TAllocator>> {
94 let result = unsafe { CArcArray::internal_abandon(&mut carc) };
95 core::mem::forget(carc);
96 result
97 }
98
99 #[inline(always)]
106 #[must_use]
107 pub const fn into_raw_ptr(carc: Self) -> *mut u8 {
108 let ptr = carc.internal.raw_ptr();
109 core::mem::forget(carc);
110 ptr
111 }
112
113 #[inline(always)]
124 pub const unsafe fn from_raw_ptr(ptr: *mut u8) -> Self {
125 let internal = InternalArcArray::from_raw_ptr(ptr);
126 Self { internal }
127 }
128
129 unsafe fn internal_abandon(carc: &mut Self) -> Option<CWeakArray<T, TAllocator>> {
130 let mut internal = unsafe { core::ptr::read(&raw const carc.internal) };
131 let prev = internal.strong().fetch_sub(1, Ordering::Release);
132 if prev > 1 {
133 return None;
134 }
135
136 if core::mem::needs_drop::<T>() {
137 for item in internal.data_slice_mut() {
138 unsafe { core::ptr::drop_in_place(item) };
139 }
140 }
141
142 fence(Ordering::Acquire);
144
145 Some(CWeakArray::from_internal(internal))
146 }
147}
148
149impl<T, TAllocator: Allocator> Drop for CArcArray<T, TAllocator> {
150 fn drop(&mut self) {
151 let _ = unsafe { CArcArray::internal_abandon(self) };
152 }
153}
154
155impl<T, TAllocator: Allocator> AsRef<[T]> for CArcArray<T, TAllocator> {
156 fn as_ref(&self) -> &[T] {
157 self.internal.data_slice()
158 }
159}
160
161impl<T, TAllocator: Allocator> Deref for CArcArray<T, TAllocator> {
162 type Target = [T];
163
164 fn deref(&self) -> &Self::Target {
165 self.internal.data_slice()
166 }
167}
168
169impl<T, TAllocator: Allocator> Borrow<[T]> for CArcArray<T, TAllocator> {
170 fn borrow(&self) -> &[T] {
171 self.internal.data_slice()
172 }
173}
174
175impl<T, TAllocator: Allocator> Clone for CArcArray<T, TAllocator> {
176 fn clone(&self) -> Self {
177 self.try_clone()
178 .expect("CArcArray strong reference count is too high. Cannot exceed {MAX_REFERENCES}")
179 }
180}
181
182impl<T, TAllocator: Allocator> TryClone for CArcArray<T, TAllocator> {
183 type Error = MaxReferencesExceededError;
184
185 fn try_clone(&self) -> Result<Self, Self::Error> {
186 let internal_clone = self.internal.raw_clone();
187 let prev_value = internal_clone.strong().fetch_add(1, Ordering::Relaxed);
188 if prev_value >= MAX_REFERENCES {
189 internal_clone.strong().fetch_sub(1, Ordering::Relaxed);
190 return Err(MaxReferencesExceededError);
191 }
192 Ok(Self {
193 internal: internal_clone,
194 })
195 }
196}
197
198impl<T: PartialEq, TAllocator: Allocator> PartialEq for CArcArray<T, TAllocator> {
199 fn eq(&self, other: &Self) -> bool {
200 if self.internal.raw_equals(&other.internal) {
201 return true;
202 }
203 self.as_ref() == other.as_ref()
204 }
205}
206
207impl<T: Eq, TAllocator: Allocator> Eq for CArcArray<T, TAllocator> {}
208
209impl<T: core::hash::Hash, TAllocator: Allocator> core::hash::Hash for CArcArray<T, TAllocator> {
210 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
211 self.as_ref().hash(state);
212 }
213}
214
215impl<T: PartialOrd, TAllocator: Allocator> PartialOrd for CArcArray<T, TAllocator> {
216 fn partial_cmp(&self, other: &Self) -> Option<CmpOrdering> {
217 self.as_ref().partial_cmp(other.as_ref())
218 }
219}
220
221impl<T: Ord, TAllocator: Allocator> Ord for CArcArray<T, TAllocator> {
222 fn cmp(&self, other: &Self) -> CmpOrdering {
223 self.as_ref().cmp(other.as_ref())
224 }
225}