wiwi/
rc.rs

1use crate::prelude::*;
2use crate::num::*;
3
4pub use self::inner::{ Counter, ThreadCounter, AtomicCounter };
5pub use self::str::{
6	RcStr,
7	RcStrWeak,
8	RcStrThread,
9	RcStrThreadWeak,
10	RcStrAtomic,
11	RcStrAtomicWeak
12};
13
14/// This module encapsulates and provides low level manipulation APIs on
15/// a raw and opaque inner reference counting pointer
16mod inner;
17mod str;
18
19/// Reference counted thin pointer, that can hold one sized
20/// value and one (dynamically sized) slice
21#[repr(transparent)]
22pub struct Rc<C, V, S>
23where
24	C: Counter
25{
26	/// Opaque reference to inner data
27	inner: inner::RcInner<C, V, S>
28}
29
30/// Weak pointer to a reference counted thin pointer [`Rc`]
31#[repr(transparent)]
32pub struct RcWeak<C, V, S>
33where
34	C: Counter
35{
36	/// Opaque reference to inner data
37	inner: inner::RcInner<C, V, S>
38}
39
40/// Single threaded reference counting thin pointer
41pub type RcThread<V, S = ()> = Rc<ThreadCounter, V, S>;
42
43/// Weak pointer to a single threaded reference counted thin pointer [`RcThread`]
44pub type RcThreadWeak<V, S = ()> = RcWeak<ThreadCounter, V, S>;
45
46/// Atomically counted reference counting thin pointer
47pub type RcAtomic<V, S = ()> = Rc<AtomicCounter, V, S>;
48
49/// Weak pointer to an atomically counted reference counted thin pointer [`RcAtomic`]
50pub type RcAtomicWeak<V, S = ()> = RcWeak<AtomicCounter, V, S>;
51
52impl<C, V> Rc<C, V, ()>
53where
54	C: Counter
55{
56	/// Creates a reference counter from a (sized) value, storing it in the `value`
57	/// field
58	#[inline]
59	pub fn from_value(value: V) -> Self {
60		Self { inner: inner::new_from_value(value) }
61	}
62}
63
64impl<C, S> Rc<C, (), S>
65where
66	C: Counter
67{
68	/// Creates a reference counter from an array, storing it in the `slice` field
69	/// and erasing the array length from the type
70	///
71	/// If you want to keep the const length of the array, you should use
72	/// [`from_value`](Rc::from_value) instead. The memory usage of the RC
73	/// allocation actually does not differ between these two.
74	#[inline]
75	pub fn from_array_into_slice<const N: usize>(array: [S; N]) -> Self {
76		Self { inner: inner::new_from_array_into_slice(array) }
77	}
78}
79
80impl<C, S> Rc<C, (), S>
81where
82	C: Counter,
83	S: Clone
84{
85	/// Creates a reference counter from a slice, cloning all elements into the
86	/// `slice` field
87	///
88	/// If your slice contains elements that implement copy, you should use
89	/// [`from_slice_copy`](Rc::from_slice_copy) instead, which can be more
90	/// efficient. (Rust, specialisation when?)
91	#[inline]
92	pub fn from_slice_clone(slice: &[S]) -> Self {
93		Self { inner: inner::new_from_slice_clone(slice) }
94	}
95}
96
97impl<C, S> Rc<C, (), S>
98where
99	C: Counter,
100	S: Copy
101{
102	/// Creates a reference counter from a slice, copying all elements into
103	/// the `slice` field
104	#[inline]
105	pub fn from_slice_copy(slice: &[S]) -> Self {
106		Self { inner: inner::new_from_slice_copy(slice) }
107	}
108}
109
110impl<C, V, S> Rc<C, V, S>
111where
112	C: Counter
113{
114	/// Creates a reference counter from a value and an array, with the array
115	/// being stored in the `slice` field
116	#[inline]
117	pub fn from_value_and_array_into_slice<const N: usize>(value: V, array: [S; N]) -> Self {
118		Self { inner: inner::new_from_value_and_array_into_slice(value, array) }
119	}
120}
121
122impl<C, V, S> Rc<C, V, S>
123where
124	C: Counter,
125	S: Clone
126{
127	/// Creates a reference counter from a value and a slice, cloning all
128	/// elements of the slice into the `slice` field
129	///
130	/// If your slice contains elements that implement copy, you should use
131	/// [`from_value_and_slice_copy`](Rc::from_value_and_slice_copy) instead,
132	/// which can be more efficient. (Rust, specialisation when?)
133	#[inline]
134	pub fn from_value_and_slice_clone(value: V, slice: &[S]) -> Self {
135		Self { inner: inner::new_from_value_and_slice_clone(value, slice) }
136	}
137}
138
139impl<C, V, S> Rc<C, V, S>
140where
141	C: Counter,
142	S: Copy
143{
144	/// Creates a reference counter from a value and a slice, copying all
145	/// elements of the slice into the `slice` field
146	#[inline]
147	pub fn from_value_and_slice_copy(value: V, slice: &[S]) -> Self {
148		Self { inner: inner::new_from_value_and_slice_copy(value, slice) }
149	}
150}
151
152impl<C, V, S> Rc<C, V, S>
153where
154	C: Counter
155{
156	/// Gets an immurable reference to the value stored in the `value` field
157	#[inline]
158	pub fn as_value_ref(&self) -> &V {
159		// SAFETY: `self.inner` is a valid instance
160		unsafe { inner::value_ref(self.inner) }
161	}
162
163	/// Gets an immurable reference to the slice stored in the `slice` field
164	#[inline]
165	pub fn as_slice_ref(&self) -> &[S] {
166		// SAFETY: `self.inner` is a valid instance
167		unsafe { inner::slice_ref(self.inner) }
168	}
169
170	/// Gets the strong pointer count
171	#[inline]
172	pub fn strong_count(&self) -> usize {
173		// SAFETY: `self.inner` is a valid instance
174		unsafe { inner::counter_ref(self.inner).strong_count() }
175	}
176
177	/// Gets the weak pointer count
178	#[inline]
179	pub fn weak_count(&self) -> usize {
180		// SAFETY: `self.inner` is a valid instance
181		unsafe { inner::counter_ref(self.inner).weak_count() - 1 }
182	}
183
184	/// "Downgrades" this pointer, returning a weak pointer [`RcWeak`] to the data
185	#[inline]
186	pub fn downgrade(&self) -> RcWeak<C, V, S> {
187		// SAFETY: `self.inner` is a valid instance
188		unsafe { inner::counter_ref(self.inner).inc_weak_for_new_ref() }
189
190		RcWeak { inner: self.inner }
191	}
192}
193
194impl<C, V, S> Clone for Rc<C, V, S>
195where
196	C: Counter
197{
198	/// Creates a new strong pointer to the same allocation,
199	/// incrementing the strong count
200	#[inline]
201	fn clone(&self) -> Self {
202		// SAFETY: `self.inner` is a valid instance
203		unsafe { inner::counter_ref(self.inner).inc_strong_for_new_ref() }
204
205		Self { inner: self.inner }
206	}
207}
208
209impl<C, V, S> Drop for Rc<C, V, S>
210where
211	C: Counter
212{
213	#[inline]
214	fn drop(&mut self) {
215		// SAFETY: `self.inner` is a valid instance
216		let should_drop = unsafe { inner::counter_ref(self.inner).dec_strong_for_drop() };
217
218		if !should_drop { return }
219
220		// SAFETY: we checked we should drop, and early exited if we shouldn't
221		unsafe { inner::drop_instance(self.inner) }
222
223		// take care of the "fake" weak ptr collectively held by strong ptrs
224		drop(RcWeak { inner: self.inner });
225	}
226}
227
228impl<C, V, S> RcWeak<C, V, S>
229where
230	C: Counter
231{
232	/// Gets the strong pointer count
233	#[inline]
234	pub fn strong_count(&self) -> usize {
235		// SAFETY: `self.inner` is a valid instance
236		unsafe { inner::counter_ref(self.inner).strong_count() }
237	}
238
239	/// Gets the weak pointer count
240	#[inline]
241	pub fn weak_count(&self) -> usize {
242		// SAFETY: `self.inner` is a valid instance
243		let weak = unsafe { inner::counter_ref(self.inner).weak_count() };
244
245		// SAFETY: same as above
246		let strong = unsafe { inner::counter_ref(self.inner).strong_count() };
247
248		weak - (strong > 0).into_usize()
249	}
250
251	/// "Upgrades" this pointer, returning a strong pointer [`Rc`] to the data
252	/// if there are still other strong pointers to it
253	#[inline]
254	pub fn upgrade(&self) -> Option<Rc<C, V, S>> {
255		// SAFETY: `self.inner` is a valid instance
256		let should_upgrade = unsafe { inner::counter_ref(self.inner).try_inc_strong_for_upgrade() };
257
258		should_upgrade.then(|| Rc { inner: self.inner })
259	}
260}
261
262impl<C, V, S> Clone for RcWeak<C, V, S>
263where
264	C: Counter
265{
266	/// Creates a new weak pointer to the same allocation,
267	/// incrementing the weak count
268	#[inline]
269	fn clone(&self) -> Self {
270		// SAFETY: `self.inner` is a valid instance
271		unsafe { inner::counter_ref(self.inner).inc_weak_for_new_ref() }
272
273		Self { inner: self.inner }
274	}
275}
276
277impl<C, V, S> Drop for RcWeak<C, V, S>
278where
279	C: Counter
280{
281	#[inline]
282	fn drop(&mut self) {
283		// SAFETY: `self.inner` is a valid instance
284		let should_dealloc = unsafe { inner::counter_ref(self.inner).dec_weak_for_drop() };
285
286		if !should_dealloc { return }
287
288		// SAFETY: we checked we should dealloc, and early exit if we shouldn't
289		unsafe { inner::dealloc_instance(self.inner) }
290	}
291}
292
293// SAFETY: we are `Send` if the counter/value/slice are all `Send`
294unsafe impl<C, V, S> Send for Rc<C, V, S>
295where
296	C: Counter + Send,
297	V: Send,
298	S: Send
299{}
300
301// SAFETY: same as above
302unsafe impl<C, V, S> Send for RcWeak<C, V, S>
303where
304	C: Counter + Send,
305	V: Send,
306	S: Send
307{}
308
309// SAFETY: we are `Sync` if the counter/value/slice are all `Sync`
310unsafe impl<C, V, S> Sync for Rc<C, V, S>
311where
312	C: Counter + Sync,
313	V: Sync,
314	S: Sync
315{}
316
317// SAFETY: same as above
318unsafe impl<C, V, S> Sync for RcWeak<C, V, S>
319where
320	C: Counter + Sync,
321	V: Sync,
322	S: Sync
323{}