refbox/lib.rs
1//! A `Box` with weak references.
2//!
3//! A [`RefBox`] is a smart pointer that owns the data, just like a standard
4//! [`Box`]. Similarly, a RefBox cannot be cloned cheaply, and when it is
5//! dropped, the data it points to is dropped as well. However, a RefBox may
6//! have many [`Weak`] pointers to the same data. These pointers don't own the
7//! data and are reference counted, comparable to the standard library's
8//! [`std::rc::Weak`]. As long as the RefBox is alive, Weak pointers can be used to
9//! access the data from multiple places without lifetime parameters.
10//!
11//! A RefBox could be seen as a lighter alternative to the standard library's
12//! [`Rc`], [`std::rc::Weak`] and [`RefCell`] combination, in cases where there is one
13//! Rc with many Weak pointers to the same data.
14//!
15//! Note: this crate is currently **experimental**.
16//!
17//! [`Rc`]: std::rc::Rc
18//! [`RefCell`]: std::cell::RefCell
19//!
20//! ## Tradeoffs
21//!
22//! A RefBox does not differentiate between strong and weak pointers and
23//! immutable and mutable borrows. There is always a *single* strong pointer,
24//! zero, one or many weak pointers, and all borrows are mutable. This means
25//! there can only be one borrow active at any given time. In return,
26//! RefBox uses less memory, is faster to borrow from, and a Weak does not need
27//! to be upgraded to access the data.
28//!
29//! # Rc + Refcell vs. RefBox
30//!
31//! | | `Rc<RefCell<T>>` | `RefBox<T>` |
32//! |------------------|----------------------------------------------------------------|-------------------------------------------------|
33//! | Pointer kinds | Many `Rc` pointers and many `Weak` pointers | One `RefBox` pointer and many `Weak` pointers |
34//! | Clonable | Both `Rc` and `Weak` are cheap to clone | Only `Weak` is cheap to clone |
35//! | Up-/Downgrading | `Rc` is downgradable, `Weak` is upgradable | `RefBox` is downgradable |
36//! | Data access through strong pointer | `RefCell::try_borrow_mut` | `RefBox::try_borrow_mut` |
37//! | Data access through weak pointer | 1. `Weak::upgrade`<br>2. `RefCell::try_borrow_mut`<br>3. Drop temporary `Rc` | `Weak::try_borrow_mut` |
38//! | Simultaneous borrows | One mutable OR multiple immutable | One (mutable or immutable) |
39//! | `T::drop` happens when | When all `Rc`s are dropped | When the single `RefBox` is dropped |
40//! | Max number of `Weak` pointers | `usize::MAX` | `u32::MAX` |
41//! | Heap overhead | 64-bit: 24 bytes<br>32-bit: 12 bytes | 8 bytes<br>With cyclic_stable enabled on 64-bit: 24 bytes<br>With cyclic_stable enabled on 32-bit: 12 bytes |
42//! | Performance | Cloning is fast, mutating is slow | Cloning is a tiny bit slower, mutating is much faster |
43//!
44//! # Examples
45//!
46//! ```
47//! use refbox::RefBox;
48//!
49//! fn main() {
50//! // Create a RefBox.
51//! let ref_box = RefBox::new(100);
52//!
53//! // Create a weak reference.
54//! let weak = RefBox::downgrade(&ref_box);
55//!
56//! // Access the data.
57//! let borrow = weak.try_borrow_mut().unwrap();
58//! assert_eq!(*borrow, 100);
59//! }
60//! ```
61//!
62//! # Optional Features
63//!
64//! * **cyclic_stable**: Enables the `RefBox::new_cyclic()` method on the stable release channel
65//! of Rust. This allows you to create data structures that contain weak references to (parts of)
66//! themselves in one go. To make it work, the memory layout of the type `T` is saved in the heap
67//! part of the `RefBox`. This increases the memory size of the heap part with `2 * usize`.
68//! * **cyclic**: Enables the `RefBox::new_cyclic()` method on the nightly release channel without
69//! increasing the memory size of the heap part. This allows you to create data structures that
70//! contain weak references to (parts of) themselves in one go. Requires the nightly feature
71//! [layout_for_ptr].
72//!
73//! [layout_for_ptr]: https://github.com/rust-lang/rust/issues/69835
74
75// The optional "cyclic" feature, which activates the `RefBox::<T>::new_cyclic()`
76// method, requires the Nightly feature "layout_for_ptr", as we need to be able
77// to get the layout of `T` through a raw pointer to deallocate it.
78#![cfg_attr(feature = "cyclic", feature(layout_for_ptr))]
79
80mod internals;
81
82use core::fmt;
83use core::marker::PhantomData;
84use core::ops::{Deref, DerefMut};
85use core::ptr::NonNull;
86use std::error;
87
88use internals::{RefBoxHeap, RefBoxHeapInner, Status, WeakCount};
89
90///////////////////////////////////////////////////////////////////////////////
91// Helpers
92///////////////////////////////////////////////////////////////////////////////
93
94/// Coerces a `RefBox<T>` into a `RefBox<dyn Trait>` on stable Rust.
95///
96/// Normally, performing custom coercions requires the [`CoerceUnsized`] trait
97/// which is only available on Nightly Rust. This macro bypasses this trait by
98/// performing the actual coercion in the raw pointer domain, which is
99/// perfectly possible on Stable Rust.
100///
101/// # Examples
102///
103/// ```
104/// use std::any::Any;
105/// use refbox::{coerce, RefBox};
106///
107/// struct SomeStruct;
108/// trait SomeTrait {}
109/// impl SomeTrait for SomeStruct {}
110///
111/// let ref_box = RefBox::new(SomeStruct);
112///
113/// let dyn_ref_box = coerce!(ref_box => dyn SomeTrait);
114///
115/// ```
116///
117/// [`CoerceUnsized`]: std::ops::CoerceUnsized
118#[macro_export]
119macro_rules! coerce {
120 ($ref_box:expr => $into_type:ty) => {{
121 let __raw = $crate::RefBox::into_raw($ref_box);
122 let __out: $crate::RefBox<$into_type> = unsafe { $crate::RefBox::from_raw(__raw) };
123 __out
124 }};
125}
126
127/// Coerces a `Weak<T>` into a `Weak<dyn Trait>` on stable Rust.
128///
129/// Normally, performing custom coercions requires the [`CoerceUnsized`] trait
130/// which is only available on Nightly Rust. This macro bypasses this trait by
131/// performing the actual coercion in the raw pointer domain, which is
132/// perfectly possible on Stable Rust.
133///
134/// # Examples
135///
136/// ```
137/// use std::any::Any;
138/// use refbox::{coerce_weak, RefBox, Weak};
139///
140/// struct SomeStruct;
141/// trait SomeTrait {}
142/// impl SomeTrait for SomeStruct {}
143///
144/// let ref_box = RefBox::new(SomeStruct);
145/// let weak_box = RefBox::downgrade(&ref_box);
146///
147/// let dyn_weak = coerce_weak!(weak_box => dyn SomeTrait);
148///
149/// ```
150///
151/// [`CoerceUnsized`]: std::ops::CoerceUnsized
152#[macro_export]
153macro_rules! coerce_weak {
154 ($weak:expr => $into_type:ty) => {{
155 let __raw = $crate::Weak::into_raw($weak);
156 let __out: $crate::Weak<$into_type> = unsafe { $crate::Weak::from_raw(__raw) };
157 __out
158 }};
159}
160
161///////////////////////////////////////////////////////////////////////////////
162// RefBox
163///////////////////////////////////////////////////////////////////////////////
164
165/// A smart pointer with many reference-counted weak references.
166///
167/// See the [module](crate) documentation for more information.
168///
169/// # Accessing the data behind the RefBox
170///
171/// See [`RefBox::try_borrow_mut`], [`RefBox::try_borrow_mut_or_else`] and
172/// [`RefBox::try_access_mut`].
173///
174/// Note: because all borrows are guarded by a single flag, only one borrow is possible at a time
175/// and all borrows are mutable.
176pub struct RefBox<T: ?Sized> {
177 ptr: NonNull<RefBoxHeap<T>>,
178 /// A RefBox owns the data and may call `T::drop`.
179 _p: PhantomData<RefBoxHeap<T>>,
180}
181
182impl<T: ?Sized> Drop for RefBox<T> {
183 fn drop(&mut self) {
184 unsafe { internals::drop_ref_box(self.ptr) };
185 }
186}
187
188impl<T: ?Sized + fmt::Debug> fmt::Debug for RefBox<T> {
189 /// Tries to access the data and write a debug representation of it.
190 /// If accessing fails, it only writes the pointer value.
191 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
192 match self.try_borrow_mut() {
193 Ok(this) => f
194 .debug_tuple("RefBox")
195 .field(&self.ptr)
196 .field(&&*this)
197 .finish(),
198 Err(_) => f.debug_tuple("RefBox").field(&self.ptr).finish(),
199 }
200 }
201}
202
203impl<T: ?Sized> PartialEq<Weak<T>> for RefBox<T> {
204 fn eq(&self, other: &Weak<T>) -> bool {
205 other.is(self)
206 }
207}
208
209impl<T: Default> Default for RefBox<T> {
210 #[inline]
211 fn default() -> Self {
212 Self::new(T::default())
213 }
214}
215
216impl<T> From<T> for RefBox<T> {
217 #[inline]
218 fn from(val: T) -> Self {
219 Self::new(val)
220 }
221}
222
223impl<T> RefBox<T> {
224 /// Creates a new `RefBox` reference counted pointer.
225 pub fn new(value: T) -> Self {
226 internals::new_ref_box(value)
227 }
228
229 /// Creates a new `RefBox` pointer through a closure which receives a
230 /// [`Weak`] pointer to the same data. Use this to create data structures
231 /// that contain weak references to themselves.
232 ///
233 /// Note: if you try to borrow the data in the closure, you will get a
234 /// [`BorrowError::Dropped`] error.
235 ///
236 /// Note: only available if either the `cyclic` or `cyclic_stable` feature is enabled.
237 ///
238 /// # Examples
239 ///
240 /// ```
241 /// use refbox::{Weak, RefBox};
242 ///
243 /// struct Node {
244 /// parent: Option<Weak<Node>>,
245 /// child: Option<RefBox<Node>>,
246 /// }
247 ///
248 /// let node = RefBox::new_cyclic(|me| {
249 /// let child = RefBox::new(Node {
250 /// parent: Some(me.clone()),
251 /// child: None,
252 /// });
253 ///
254 /// Node {
255 /// parent: None,
256 /// child: Some(child),
257 /// }
258 /// });
259 /// ```
260 #[cfg(any(feature = "cyclic", feature = "cyclic_stable"))]
261 pub fn new_cyclic<F: FnOnce(&Weak<T>) -> T>(op: F) -> Self {
262 internals::new_cyclic_ref_box(op)
263 }
264}
265
266impl<T: ?Sized> RefBox<T> {
267 /// Returns a read-only reference to the heap part of the `RefBox`.
268 #[inline(always)]
269 fn heap(&self) -> &RefBoxHeapInner {
270 // SAFETY (1): RefBox guarantees the heap memory stays alive at least
271 // as long as the RefBox is alive.
272 // SAFETY (2): We only ever access this through a shared reference so
273 // we don't have to account for possible mutable references.
274 // SAFETY (3): Because this is a `RefBox` we know the data field
275 // is initialized.
276 let ptr = self.ptr.as_ptr();
277 unsafe { &(*ptr).inner }
278 }
279
280 /// Tries to borrow the data mutably.
281 ///
282 /// # Returns
283 ///
284 /// * `Ok(Borrow)` if the borrow was successful
285 /// * `Err(BorrowError::Borrowed)` if the data was already borrowed
286 #[inline]
287 pub fn try_borrow_mut(&self) -> Result<Borrow<T>, BorrowError> {
288 self.try_borrow_mut_or_else(|| BorrowError::Borrowed)
289 }
290
291 /// Tries to borrow the data mutably and returns a custom error if
292 /// borrowing fails.
293 pub fn try_borrow_mut_or_else<E>(
294 &self,
295 err_borrowed: impl FnOnce() -> E,
296 ) -> Result<Borrow<T>, E> {
297 match self.heap().status() {
298 Status::Available => Ok(unsafe { Borrow::new(self.ptr.as_ref()) }),
299 Status::Borrowed => Err(err_borrowed()),
300 Status::Dropped | Status::DroppedWhileBorrowed => unreachable!(),
301 }
302 }
303
304 /// Provides access to the data through a closure.
305 ///
306 /// If the data is already borrowed, the closure is not executed and an
307 /// error is returned. Otherwise, the closure is executed and the output of
308 /// the closure is returned.
309 ///
310 /// # Returns
311 ///
312 /// * `Ok(R)` if the access was successful
313 /// * `Err(BorrowError::Borrowed)` if the data was already borrowed
314 pub fn try_access_mut<R, F: FnOnce(&mut T) -> R>(&self, op: F) -> Result<R, BorrowError> {
315 let mut borrow = self.try_borrow_mut()?;
316 Ok(op(&mut *borrow))
317 }
318
319 /// Creates a [`Weak`] reference to the data.
320 ///
321 /// # Panics
322 ///
323 /// Panics if the number of Refs overflows `u32::MAX`.
324 ///
325 /// See [`Self::try_downgrade`] for a version that does not panic.
326 pub fn downgrade(&self) -> Weak<T> {
327 self.heap().increase_weak_count();
328 Weak { ptr: self.ptr }
329 }
330
331 /// Tries to create a [`Weak`] pointer to the data.
332 ///
333 /// # Returns
334 ///
335 /// * `Some(Weak)` if it was successful.
336 /// * `None` if the number of weak pointers overflowed `u32::MAX`.
337 pub fn try_downgrade(&self) -> Option<Weak<T>> {
338 if self.heap().try_increase_weak_count() {
339 Some(Weak { ptr: self.ptr })
340 } else {
341 None
342 }
343 }
344
345 /// Returns the number of [`Weak`]s pointing to this RefBox.
346 pub fn weak_count(&self) -> WeakCount {
347 self.heap().weak_count()
348 }
349
350 /// Returns an immutable reference to the data without checking if
351 /// the data is already mutably borrowed.
352 ///
353 /// # Safety
354 ///
355 /// Ensure there are no mutable references to `T`.
356 pub unsafe fn get_unchecked(&self) -> &T {
357 // SAFETY: the caller must uphold the safety requirements
358 unsafe { self.ptr.as_ref().data_ref() }
359 }
360
361 /// Returns a mutable reference to the data without checking if
362 /// the data is already mutably borrowed.
363 ///
364 /// # Safety
365 ///
366 /// Ensure there are no other references to `T`.
367 pub unsafe fn get_mut_unchecked(&mut self) -> &mut T {
368 // SAFETY: the caller must uphold the safety requirements
369 unsafe { self.ptr.as_ref().data_mut() }
370 }
371
372 /// Returns a raw pointer to `T`.
373 pub fn as_ptr(&self) -> *const T {
374 let ptr = self.ptr.as_ptr();
375
376 // SAFETY (1): ptr is safe to dereference, see Self::heap().
377 // SAFETY (2): UnsafeCell is `#[repr(transparent)]`, which means
378 // a pointer to the cell is also a pointer to its only field.
379 // SAFETY (3): RefBox could be borrowed, so use &raw to ensure no reference is created
380 // while there is a mutable reference.
381 unsafe { &raw const (*ptr).data as *const T }
382 }
383
384 /// Turns the `RefBox` into a raw pointer.
385 pub fn into_raw(self) -> *mut RefBoxHeap<T> {
386 let ptr = self.ptr.as_ptr();
387 std::mem::forget(self);
388 ptr
389 }
390
391 /// Creates a `RefBox` from a raw pointer.
392 ///
393 /// # Safety
394 ///
395 /// Ensure `ptr` is a valid pointer to a `RefBoxHeap<T>` instance.
396 pub unsafe fn from_raw(ptr: *mut RefBoxHeap<T>) -> Self {
397 // SAFETY: the caller must uphold the safety requirements
398 Self {
399 ptr: unsafe { NonNull::new_unchecked(ptr) },
400 _p: PhantomData,
401 }
402 }
403
404 /// Casts a `RefBox<T>` to a `RefBox<U>`.
405 ///
406 /// # Safety
407 ///
408 /// Ensure `T` can be safely cast to `U`.
409 pub unsafe fn cast<U>(self) -> RefBox<U> {
410 let raw_ptr = self.into_raw();
411
412 // SAFETY: the caller must uphold the safety requirements
413 unsafe { RefBox::from_raw(raw_ptr as _) }
414 }
415
416 /// Returns the current status of the heap part for testing purposes.
417 #[cfg(test)]
418 fn status(&self) -> Status {
419 self.heap().status()
420 }
421}
422
423///////////////////////////////////////////////////////////////////////////////
424// Weak
425///////////////////////////////////////////////////////////////////////////////
426
427/// A weak reference-counted reference to a [`RefBox`].
428///
429/// See the [module](crate) documentation for more information.
430///
431/// # Accessing the data behind the Weak
432///
433/// See [`Weak::try_borrow_mut`], [`Weak::try_borrow_mut_or_else`] and
434/// [`Weak::try_access_mut`].
435///
436/// Note: because all borrows are guarded by a single flag, only one borrow is possible at a time
437/// and all borrows are mutable.
438pub struct Weak<T: ?Sized> {
439 ptr: NonNull<RefBoxHeap<T>>,
440}
441
442impl<T: ?Sized> Drop for Weak<T> {
443 fn drop(&mut self) {
444 // SAFETY: the `Weak` cannot be used anymore after this point.
445 unsafe { internals::drop_weak(self.ptr) };
446 }
447}
448
449impl<T: ?Sized> Clone for Weak<T> {
450 /// Copies the reference and increases the reference counter.
451 ///
452 /// # Panics
453 ///
454 /// Panics if the number of Refs overflows `u32::MAX`.
455 fn clone(&self) -> Self {
456 self.heap().increase_weak_count();
457 Weak { ptr: self.ptr }
458 }
459}
460
461impl<T: ?Sized> fmt::Debug for Weak<T> {
462 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
463 f.debug_tuple("Weak").field(&self.ptr).finish()
464 }
465}
466
467impl<T: ?Sized> PartialEq for Weak<T> {
468 /// Returns true if both `Weak` pointers point to the same instance.
469 ///
470 /// This compares the pointer addresses, not the actual objects themselves,
471 /// which makes it very fast.
472 fn eq(&self, other: &Self) -> bool {
473 std::ptr::addr_eq(self.ptr.as_ptr(), other.ptr.as_ptr())
474 }
475}
476
477impl<T: ?Sized> PartialEq<RefBox<T>> for Weak<T> {
478 fn eq(&self, other: &RefBox<T>) -> bool {
479 self.is(other)
480 }
481}
482
483impl<T: ?Sized> Eq for Weak<T> {}
484
485impl<T: ?Sized> Weak<T> {
486 /// Returns a read-only reference to the heap part of the `Weak`.
487 #[inline(always)]
488 fn heap(&self) -> &RefBoxHeapInner {
489 // SAFETY (1): Weak guarantees the heap memory stays alive at
490 // least as long as the Weak is alive.
491 // SAFETY (2): We only ever access this through a shared reference so
492 // we don't have to account for possible mutable references.
493 // SAFETY (3): We make sure not to create a reference covering the
494 // `data` field of `RefBoxHeap` as it may contain uninitialized data.
495 let ptr = self.ptr.as_ptr();
496 unsafe { &(*ptr).inner }
497 }
498
499 /// Tries to borrow the data mutably.
500 ///
501 /// # Returns
502 ///
503 /// * `Ok(Borrow)` if the borrow was successful
504 /// * `Err(BorrowError::Borrowed)` if the data was already borrowed
505 /// * `Err(BorrowError::Dropped)` if the owning [`RefBox`] was dropped
506 #[inline]
507 pub fn try_borrow_mut(&self) -> Result<Borrow<T>, BorrowError> {
508 self.try_borrow_mut_or_else(|| BorrowError::Borrowed, || BorrowError::Dropped)
509 }
510
511 /// Tries to borrow the data mutably and returns a custom error if
512 /// borrowing fails.
513 pub fn try_borrow_mut_or_else<E>(
514 &self,
515 err_borrowed: impl FnOnce() -> E,
516 err_dropped: impl FnOnce() -> E,
517 ) -> Result<Borrow<T>, E> {
518 match self.heap().status() {
519 Status::Available => Ok(unsafe { Borrow::new(self.ptr.as_ref()) }),
520 Status::Borrowed => Err(err_borrowed()),
521 Status::Dropped | Status::DroppedWhileBorrowed => Err(err_dropped()),
522 }
523 }
524
525 /// Provides access to the data through a closure.
526 ///
527 /// If the data is already borrowed or the owning [`RefBox`] is dropped,
528 /// the closure is not executed and an error is returned. Otherwise, the
529 /// closure is executed and the output of the closure is returned.
530 ///
531 /// # Returns
532 ///
533 /// * `Ok(R)` if the access was successful
534 /// * `Err(BorrowError::Borrowed)` if the data was already borrowed
535 /// * `Err(BorrowError::Dropped)` if the owning [`RefBox`] was dropped
536 pub fn try_access_mut<R, F: FnOnce(&mut T) -> R>(&self, op: F) -> Result<R, BorrowError> {
537 let mut borrow = self.try_borrow_mut()?;
538 Ok(op(&mut *borrow))
539 }
540
541 /// Tries to clone the weak reference to the data.
542 ///
543 /// # Returns
544 ///
545 /// * `Some(Weak)` if it was successful.
546 /// * `None` if the number of weak pointers overflowed `u32::MAX`.
547 pub fn try_clone(&self) -> Option<Weak<T>> {
548 if self.heap().try_increase_weak_count() {
549 Some(Weak { ptr: self.ptr })
550 } else {
551 None
552 }
553 }
554
555 /// Returns the total number of [`Weak`] pointers that point to the same instance as this one.
556 pub fn weak_count(&self) -> WeakCount {
557 self.heap().weak_count()
558 }
559
560 /// Returns true if the owner of the data is alive.
561 pub fn is_alive(&self) -> bool {
562 self.heap().is_alive()
563 }
564
565 /// Returns true if the data is currently mutably borrowed.
566 pub fn is_borrowed(&self) -> bool {
567 self.heap().is_borrowed()
568 }
569
570 /// Returns true if this `Weak` and the supplied [`RefBox`] point to the same instance.
571 pub fn is(&self, owner: &RefBox<T>) -> bool {
572 std::ptr::addr_eq(self.ptr.as_ptr(), owner.ptr.as_ptr())
573 }
574
575 /// Returns an immutable reference to the data without checking if
576 /// the data is already mutably borrowed or dropped.
577 ///
578 /// # Safety
579 ///
580 /// 1. Ensure there are no mutable references to `T`.
581 /// 2. Ensure `T` is fully initialized (don't use this in
582 /// `RefBox::new_cyclic`).
583 /// 3. Ensure the owning `RefBox` is alive for the entire lifetime
584 /// of the returned reference.
585 pub unsafe fn get_unchecked(&self) -> &T {
586 // SAFETY: the caller must uphold the safety requirements
587 unsafe { self.ptr.as_ref().data_ref() }
588 }
589
590 /// Returns a mutable reference to the data without checking if
591 /// the data is already mutably borrowed or dropped.
592 ///
593 /// # Safety
594 ///
595 /// 1. Ensure there are no other references to `T`.
596 /// 2. Ensure `T` is fully initialized (don't use this in
597 /// `RefBox::new_cyclic`).
598 /// 3. Ensure the owning `RefBox` is alive for the entire lifetime
599 /// of the returned reference.
600 pub unsafe fn get_mut_unchecked(&mut self) -> &mut T {
601 // SAFETY: the caller must uphold the safety requirements
602 unsafe { self.ptr.as_ref().data_mut() }
603 }
604
605 /// Returns a raw pointer to `T`.
606 pub fn as_ptr(&self) -> *const T {
607 let ptr = self.ptr.as_ptr();
608
609 // SAFETY (1): ptr is safe to dereference, see Self::heap().
610 // SAFETY (2): UnsafeCell is `#[repr(transparent)]`, which means
611 // a pointer to the cell is also a pointer to its only field.
612 // SAFETY (3): data could be uninitialized, so use &raw to ensure no reference is created
613 unsafe { &raw const (*ptr).data as *const T }
614 }
615
616 /// Turns the `Weak` into a raw pointer.
617 pub fn into_raw(self) -> *mut RefBoxHeap<T> {
618 let ptr = self.ptr.as_ptr();
619 std::mem::forget(self);
620 ptr
621 }
622
623 /// Creates a `Weak` from a raw pointer.
624 ///
625 /// # Safety
626 ///
627 /// Ensure `ptr` is a valid pointer to a `RefBoxHeap<T>`.
628 pub unsafe fn from_raw(ptr: *mut RefBoxHeap<T>) -> Self {
629 // SAFETY: the caller must uphold the safety requirements
630 let ptr = unsafe { NonNull::new_unchecked(ptr) };
631 Self { ptr }
632 }
633
634 /// Casts a `Weak<T>` to a `Weak<U>`.
635 ///
636 /// # Safety
637 ///
638 /// Ensure `T` can be safely cast to `U`.
639 pub unsafe fn cast<U>(self) -> Weak<U> {
640 let raw_ptr = self.into_raw();
641
642 // SAFETY: the caller must uphold the safety requirements
643 unsafe { Weak::from_raw(raw_ptr as _) }
644 }
645
646 /// Returns the current status of the heap part for testing purposes.
647 #[cfg(test)]
648 fn status(&self) -> Status {
649 self.heap().status()
650 }
651}
652
653///////////////////////////////////////////////////////////////////////////////
654// Borrow
655///////////////////////////////////////////////////////////////////////////////
656
657/// A mutable borrow as a RAII-guard of a [`RefBox`] or [`Weak`].
658///
659/// See the [module](crate) documentation for more information.
660pub struct Borrow<'ptr, T: ?Sized> {
661 pub(crate) heap: &'ptr RefBoxHeap<T>,
662 /// A borrow is a mutable reference to the data.
663 pub(crate) _p: PhantomData<&'ptr mut T>,
664}
665
666impl<'ptr, T: ?Sized> Borrow<'ptr, T> {
667 /// Creates a new borrow.
668 #[inline]
669 unsafe fn new(heap: &'ptr RefBoxHeap<T>) -> Self {
670 heap.inner.start_borrow();
671 Self {
672 heap,
673 _p: PhantomData,
674 }
675 }
676}
677
678impl<'ptr, T: ?Sized> Drop for Borrow<'ptr, T> {
679 fn drop(&mut self) {
680 // SAFETY: The borrow cannot be used anymore after this point.
681 unsafe { internals::drop_borrow(self.heap) };
682 }
683}
684
685impl<'ptr, T: ?Sized> Deref for Borrow<'ptr, T> {
686 type Target = T;
687
688 fn deref(&self) -> &Self::Target {
689 // SAFETY: There can only ever be one `Borrow` to the same
690 // data, so we're sure there are no mutable references.
691 unsafe { self.heap.data_ref() }
692 }
693}
694
695impl<'ptr, T: ?Sized> DerefMut for Borrow<'ptr, T> {
696 fn deref_mut(&mut self) -> &mut Self::Target {
697 // SAFETY: There can only ever be one `Borrow` to the same
698 // data, so we're sure there are no other references.
699 unsafe { self.heap.data_mut() }
700 }
701}
702
703impl<'ptr, T: ?Sized + fmt::Debug> fmt::Debug for Borrow<'ptr, T> {
704 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
705 f.debug_tuple("Borrow").field(&self.deref()).finish()
706 }
707}
708
709///////////////////////////////////////////////////////////////////////////////
710// Errors
711///////////////////////////////////////////////////////////////////////////////
712
713/// An error that may occur during borrowing of [`RefBox`] or [`Weak`].
714#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
715pub enum BorrowError {
716 Borrowed,
717 Dropped,
718}
719
720impl fmt::Display for BorrowError {
721 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
722 match self {
723 BorrowError::Borrowed => write!(f, "already borrowed"),
724 BorrowError::Dropped => write!(f, "owner dropped"),
725 }
726 }
727}
728
729impl error::Error for BorrowError {}
730
731///////////////////////////////////////////////////////////////////////////////
732// Tests
733///////////////////////////////////////////////////////////////////////////////
734
735#[cfg(test)]
736mod tests {
737 use std::cell::Cell;
738 use std::panic;
739 use std::rc::Rc;
740
741 use crate::RefBox;
742 use crate::internals::{RefBoxHeap, Status};
743
744 #[test]
745 fn ref_box_new() {
746 let ref_box = RefBox::new(123456);
747 assert_eq!(unsafe { *ref_box.get_unchecked() }, 123456);
748 drop(ref_box);
749 }
750
751 /// The weak count after creation should be 0.
752 #[test]
753 fn ref_box_new_weak_count() {
754 let ref_box = RefBox::new(123456);
755 assert_eq!(ref_box.weak_count(), 0);
756 drop(ref_box);
757 }
758
759 #[test]
760 #[cfg(any(feature = "cyclic", feature = "cyclic_stable"))]
761 fn ref_box_new_cyclic() {
762 let ref_box = RefBox::new_cyclic(|_weak| 13579);
763 assert_eq!(unsafe { *ref_box.get_unchecked() }, 13579);
764 drop(ref_box);
765 }
766
767 /// The weak count in the closure should be 1, and the weak count after creation should be 0.
768 #[test]
769 #[cfg(any(feature = "cyclic", feature = "cyclic_stable"))]
770 fn ref_box_new_cyclic_weak_count() {
771 let ref_box = RefBox::new_cyclic(|weak| {
772 assert_eq!(weak.weak_count(), 1);
773 });
774 assert_eq!(ref_box.weak_count(), 0);
775 drop(ref_box);
776 }
777
778 /// The Weak in the closure should point to the same instance as the returned RefBox.
779 #[test]
780 #[cfg(any(feature = "cyclic", feature = "cyclic_stable"))]
781 fn ref_box_new_cyclic_ptr_eq() {
782 let mut out_weak = None;
783 let ref_box = RefBox::new_cyclic(|weak| out_weak = Some(weak.clone()));
784 assert_eq!(ref_box.ptr.as_ptr(), out_weak.unwrap().ptr.as_ptr());
785 drop(ref_box);
786 }
787
788 /// MIRI: A panic in the closure of [`RefBox::new_cyclic`] should not leak memory.
789 #[test]
790 #[should_panic]
791 #[cfg(any(feature = "cyclic", feature = "cyclic_stable"))]
792 fn ref_box_new_cyclic_does_not_leak() {
793 let ref_box = RefBox::new_cyclic(|_weak| {
794 panic!("panic in closure!");
795 });
796 drop(ref_box);
797 }
798
799 /// A weak pointer returned from [`RefBox::downgrade`] should point to the same
800 /// instance as the RefBox.
801 #[test]
802 fn downgrade_ptr_eq() {
803 let val = 123456;
804 let ref_box = RefBox::new(val);
805 let weak = RefBox::downgrade(&ref_box);
806 assert_eq!(ref_box.ptr.as_ptr(), weak.ptr.as_ptr());
807 }
808
809 /// ['RefBox::downgrade'] should increase the weak reference count.
810 #[test]
811 fn downgrade_increases_refcount() {
812 let val = 123456;
813 let ref_box = RefBox::new(val);
814 assert_eq!(ref_box.weak_count(), 0);
815 let weak = RefBox::downgrade(&ref_box);
816 assert_eq!(ref_box.weak_count(), 1);
817 assert_eq!(weak.weak_count(), 1);
818 }
819
820 /// ['RefBox::downgrade'] should panic if the weak count overflows u32::MAX.
821 #[test]
822 fn downgrade_panics_on_max() {
823 let val = 123456;
824 let ref_box = RefBox::new(val);
825 ref_box.heap().set_weak_count(u32::MAX);
826
827 // Use catch unwind and reset weak count, otherwise MIRI will report memory leak.
828 let result = panic::catch_unwind(panic::AssertUnwindSafe(|| {
829 let weak = RefBox::downgrade(&ref_box);
830 drop(weak);
831 }));
832 assert!(result.is_err());
833
834 ref_box.heap().set_weak_count(0);
835 drop(ref_box);
836 }
837
838 /// ['RefBox::try_downgrade'] should return None if the weak count overflows
839 /// u32::MAX.
840 #[test]
841 fn try_downgrade_returns_none_on_max() {
842 let val = 123456;
843 let ref_box = RefBox::new(val);
844 ref_box.heap().set_weak_count(u32::MAX);
845 let weak = RefBox::try_downgrade(&ref_box);
846 assert!(weak.is_none());
847 drop(weak);
848 ref_box.heap().set_weak_count(0);
849 drop(ref_box);
850 }
851
852 /// ['Weak::clone'] should increase the weak reference count.
853 #[test]
854 fn cloning_weak_increases_weak_count() {
855 let val = 123456;
856 let ref_box = RefBox::new(val);
857 assert_eq!(ref_box.weak_count(), 0);
858 let weak = RefBox::downgrade(&ref_box);
859 assert_eq!(ref_box.weak_count(), 1);
860 let weak2 = weak.clone();
861 assert_eq!(ref_box.weak_count(), 2);
862 drop(weak2);
863 drop(weak);
864 }
865
866 /// ['Weak::clone'] should panic if the weak count overflows u32::MAX.
867 #[test]
868 fn cloning_weak_panics_on_max() {
869 let ref_box = RefBox::new(123456);
870 let weak = RefBox::downgrade(&ref_box);
871 weak.heap().set_weak_count(u32::MAX);
872
873 // Use catch unwind and reset refcount, otherwise MIRI will report memory leak.
874 let result = panic::catch_unwind(panic::AssertUnwindSafe(|| {
875 let weak2 = weak.clone();
876 drop(weak2);
877 }));
878 assert!(result.is_err());
879
880 drop(weak);
881 ref_box.heap().set_weak_count(0);
882 drop(ref_box);
883 }
884
885 #[test]
886 fn dropping_weak_decreases_weak_count() {
887 let val = 123456;
888 let ref_box = RefBox::new(val);
889 let weak = RefBox::downgrade(&ref_box);
890 assert_eq!(ref_box.weak_count(), 1);
891 drop(weak);
892 assert_eq!(ref_box.weak_count(), 0);
893 }
894
895 #[test]
896 fn owner_is_alive() {
897 let val = 123456;
898 let ref_box = RefBox::new(val);
899 let weak = RefBox::downgrade(&ref_box);
900 assert_eq!(weak.is_alive(), true);
901 drop(ref_box);
902 }
903
904 #[test]
905 fn owner_is_not_alive_after_dropped() {
906 let val = 123456;
907 let ref_box = RefBox::new(val);
908 let weak = RefBox::downgrade(&ref_box);
909 assert_eq!(weak.is_alive(), true);
910 drop(ref_box);
911 assert_eq!(weak.is_alive(), false);
912 }
913
914 #[test]
915 fn dropping_ref_box_drops_data() {
916 struct DropThing(Rc<Cell<bool>>);
917
918 impl Drop for DropThing {
919 fn drop(&mut self) {
920 self.0.set(true);
921 }
922 }
923
924 let drop_checker = Rc::new(Cell::new(false));
925 let ref_box = RefBox::new(DropThing(drop_checker.clone()));
926 assert_eq!(drop_checker.get(), false);
927 drop(ref_box);
928 assert_eq!(drop_checker.get(), true);
929 }
930
931 #[test]
932 fn dropping_rc_with_weak_refs_drops_data() {
933 struct DropThing(Rc<Cell<bool>>);
934
935 impl Drop for DropThing {
936 fn drop(&mut self) {
937 self.0.set(true);
938 }
939 }
940
941 let drop_checker = Rc::new(Cell::new(false));
942 let ref_box = RefBox::new(DropThing(drop_checker.clone()));
943 let weak = RefBox::downgrade(&ref_box);
944 assert_eq!(drop_checker.get(), false);
945 drop(ref_box);
946 assert_eq!(drop_checker.get(), true);
947 drop(weak);
948 }
949
950 #[test]
951 fn dropping_weak_does_not_drop_data() {
952 struct DropThing(Rc<Cell<bool>>);
953
954 impl Drop for DropThing {
955 fn drop(&mut self) {
956 self.0.set(true);
957 }
958 }
959
960 let drop_checker = Rc::new(Cell::new(false));
961 let ref_box = RefBox::new(DropThing(drop_checker.clone()));
962 let weak = RefBox::downgrade(&ref_box);
963 assert_eq!(drop_checker.get(), false);
964 drop(weak);
965 assert_eq!(drop_checker.get(), false);
966 drop(ref_box);
967 assert_eq!(drop_checker.get(), true);
968 }
969
970 #[test]
971 fn owner_is_borrowable() {
972 let ref_box = RefBox::new(123456);
973 let borrow = ref_box.try_borrow_mut_or_else(|| "was borrowed");
974 assert!(borrow.is_ok());
975 drop(borrow);
976 drop(ref_box);
977 }
978
979 #[test]
980 fn owner_is_not_borrowable_twice() {
981 let ref_box = RefBox::new(123456);
982 let borrow = ref_box.try_borrow_mut_or_else(|| "was borrowed");
983 assert!(borrow.is_ok());
984 let borrow2 = ref_box.try_borrow_mut_or_else(|| "was borrowed");
985 assert!(matches!(borrow2, Err("was borrowed")));
986 drop(borrow);
987 drop(borrow2);
988 drop(ref_box);
989 }
990
991 #[test]
992 fn weak_is_borrowable() {
993 let ref_box = RefBox::new(123456);
994 let weak = RefBox::downgrade(&ref_box);
995 let borrow = weak.try_borrow_mut_or_else(|| "was borrowed", || "was dropped");
996 assert!(matches!(borrow, Ok(_)));
997 drop(borrow);
998 drop(weak);
999 drop(ref_box);
1000 }
1001
1002 #[test]
1003 fn weak_is_not_borrowable_twice() {
1004 let ref_box = RefBox::new(123456);
1005 let weak = RefBox::downgrade(&ref_box);
1006 let borrow = weak.try_borrow_mut_or_else(|| "was borrowed", || "was dropped");
1007 assert!(matches!(borrow, Ok(_)));
1008 let borrow2 = weak.try_borrow_mut_or_else(|| "was borrowed", || "was dropped");
1009 assert!(matches!(borrow2, Err("was borrowed")));
1010 drop(borrow);
1011 drop(borrow2);
1012 drop(weak);
1013 drop(ref_box);
1014 }
1015
1016 #[test]
1017 fn weak_is_not_borrowable_if_owner_borrowed() {
1018 let ref_box = RefBox::new(123456);
1019 let weak = RefBox::downgrade(&ref_box);
1020 let borrow = ref_box.try_borrow_mut_or_else(|| "was borrowed");
1021 assert!(matches!(borrow, Ok(_)));
1022 let borrow2 = weak.try_borrow_mut_or_else(|| "was borrowed", || "was dropped");
1023 assert!(matches!(borrow2, Err("was borrowed")));
1024 drop(borrow);
1025 drop(borrow2);
1026 drop(weak);
1027 drop(ref_box);
1028 }
1029
1030 #[test]
1031 fn weak_is_not_borrowable_if_owner_dropped() {
1032 let ref_box = RefBox::new(123456);
1033 let weak = RefBox::downgrade(&ref_box);
1034 drop(ref_box);
1035 let borrow = weak.try_borrow_mut_or_else(|| "was borrowed", || "was dropped");
1036 assert!(matches!(borrow, Err("was dropped")));
1037 drop(borrow);
1038 drop(weak);
1039 }
1040
1041 #[test]
1042 fn dropping_owner_while_borrowed_delays_drops() {
1043 let ref_box = RefBox::new(123456);
1044 let weak = RefBox::downgrade(&ref_box);
1045 let borrow = weak.try_borrow_mut_or_else(|| "was borrowed", || "was dropped");
1046 assert_eq!(weak.status(), Status::Borrowed);
1047 drop(ref_box);
1048 assert_eq!(weak.status(), Status::DroppedWhileBorrowed);
1049 drop(borrow);
1050 assert_eq!(weak.status(), Status::Dropped);
1051 drop(weak);
1052 }
1053
1054 #[test]
1055 fn borrowing_changes_status() {
1056 let ref_box = RefBox::new(123456);
1057 assert_eq!(ref_box.status(), Status::Available);
1058 let borrow = ref_box.try_borrow_mut_or_else(|| "was borrowed");
1059 assert_eq!(ref_box.status(), Status::Borrowed);
1060 drop(borrow);
1061 assert_eq!(ref_box.status(), Status::Available);
1062 drop(ref_box);
1063 }
1064
1065 #[test]
1066 fn dropping_owner_changes_status() {
1067 let ref_box = RefBox::new(123456);
1068 let weak = RefBox::downgrade(&ref_box);
1069 assert_eq!(weak.status(), Status::Available);
1070 drop(ref_box);
1071 assert_eq!(weak.status(), Status::Dropped);
1072 drop(weak);
1073 }
1074
1075 #[test]
1076 #[cfg(any(feature = "cyclic", feature = "cyclic_stable"))]
1077 fn borrowing_in_cyclic_fails() {
1078 let ref_box = RefBox::new_cyclic(|weak| {
1079 let borrow = weak.try_borrow_mut_or_else(|| "was borrowed", || "was dropped");
1080 assert!(borrow.is_err());
1081 });
1082 drop(ref_box);
1083 }
1084
1085 #[test]
1086 #[cfg(any(feature = "cyclic", feature = "cyclic_stable"))]
1087 fn cloning_weak_in_cyclic_increases_refcount() {
1088 let ref_box = RefBox::new_cyclic(|weak| {
1089 let weak2 = weak.clone();
1090 assert_eq!(weak.weak_count(), 2);
1091 drop(weak2);
1092 });
1093 drop(ref_box);
1094 }
1095
1096 #[test]
1097 fn calling_getters_while_having_mutable_ref() {
1098 let ref_box = RefBox::new(123456);
1099 let mut borrow = ref_box.try_borrow_mut_or_else(|| "was borrowed").unwrap();
1100 let mut_ref = &mut *borrow;
1101 assert_eq!(ref_box.weak_count(), 0);
1102 *mut_ref = 654321;
1103 let weak = RefBox::downgrade(&ref_box);
1104 assert_eq!(ref_box.weak_count(), 1);
1105 *mut_ref = 13579;
1106 drop(borrow);
1107 drop(weak);
1108 drop(ref_box);
1109 }
1110
1111 #[test]
1112 fn single_ref_boxes_are_distinct() {
1113 let ref_box_1 = RefBox::new(123456);
1114 let ref_box_2 = RefBox::new(654321);
1115
1116 let borrow1 = ref_box_1.try_borrow_mut().unwrap();
1117 let borrow2 = ref_box_2.try_borrow_mut().unwrap();
1118
1119 assert_ne!(*borrow1, *borrow2);
1120 assert_eq!(*borrow1, 123456);
1121 assert_eq!(*borrow2, 654321);
1122
1123 drop(borrow1);
1124 drop(borrow2);
1125 drop(ref_box_1);
1126 drop(ref_box_2);
1127 }
1128
1129 /// Test if [`RefBox::as_ptr`] returns the right pointer. Run with MIRI.
1130 #[test]
1131 fn ref_box_as_ptr() {
1132 let ref_box = RefBox::new(123456);
1133 let ptr = ref_box.as_ptr();
1134
1135 let heap = unsafe { ref_box.ptr.as_ref() };
1136 let real_ptr = heap.data.get();
1137
1138 assert_eq!(ptr, real_ptr);
1139 drop(ref_box);
1140 }
1141
1142 /// Test if [`Weak::as_ptr`] returns the right pointer. Run with MIRI.
1143 #[test]
1144 fn weak_as_ptr() {
1145 let ref_box = RefBox::new(123456);
1146 let weak = RefBox::downgrade(&ref_box);
1147 let ptr = weak.as_ptr();
1148
1149 let heap = unsafe { weak.ptr.as_ref() };
1150 let real_ptr = heap.data.get();
1151
1152 assert_eq!(ptr, real_ptr);
1153 drop(weak);
1154 drop(ref_box);
1155 }
1156
1157 /// Test if the overhead of the heap part is 8 bytes when 'cyclic_stable' feature is not enabled.
1158 #[test]
1159 #[cfg(not(feature = "cyclic_stable"))]
1160 fn heap_overhead() {
1161 let layout = std::alloc::Layout::new::<RefBoxHeap<()>>();
1162 assert_eq!(layout.size(), 8);
1163 }
1164
1165 /// Test if the overhead of the heap part is 12 bytes when 'cyclic_stable' feature is enabled
1166 /// and the pointer size is 16 bits.
1167 #[test]
1168 #[cfg(feature = "cyclic_stable")]
1169 #[cfg(any(target_pointer_width = "16"))]
1170 fn heap_overhead_cyclic_stable_16bit() {
1171 let layout = std::alloc::Layout::new::<RefBoxHeap<()>>();
1172 assert_eq!(layout.size(), 12);
1173 }
1174
1175 /// Test if the overhead of the heap part is 16 bytes when 'cyclic_stable' feature is enabled
1176 /// and the pointer size is 32 bits.
1177 #[test]
1178 #[cfg(feature = "cyclic_stable")]
1179 #[cfg(any(target_pointer_width = "32"))]
1180 fn heap_overhead_cyclic_stable_32bit() {
1181 let layout = std::alloc::Layout::new::<RefBoxHeap<()>>();
1182 assert_eq!(layout.size(), 16);
1183 }
1184
1185 /// Test if the overhead of the heap part is 24 bytes when 'cyclic_stable' feature is enabled
1186 /// and the pointer size is 64 bits.
1187 #[test]
1188 #[cfg(feature = "cyclic_stable")]
1189 #[cfg(any(target_pointer_width = "64"))]
1190 fn heap_overhead_cyclic_stable_64bit() {
1191 let layout = std::alloc::Layout::new::<RefBoxHeap<()>>();
1192 assert_eq!(layout.size(), 24);
1193 }
1194}