1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
//! Inherent implementation and trait implementations for the [`Shared`] type. use core::fmt; use core::marker::PhantomData; use core::ops::Deref; use typenum::Unsigned; use crate::internal::Internal; use crate::pointer::{Marked, MarkedNonNull, MarkedPointer, NonNullable}; use crate::{Reclaim, Shared, Unprotected}; //////////////////////////////////////////////////////////////////////////////////////////////////// // impl Copy & Clone //////////////////////////////////////////////////////////////////////////////////////////////////// impl<'g, T, R, N> Clone for Shared<'g, T, N, R> { #[inline] fn clone(&self) -> Self { Self { inner: self.inner, _marker: PhantomData } } } impl<'g, T, R, N> Copy for Shared<'g, T, R, N> {} //////////////////////////////////////////////////////////////////////////////////////////////////// // impl MarkedPointer //////////////////////////////////////////////////////////////////////////////////////////////////// impl<'g, T, R: Reclaim, N: Unsigned> MarkedPointer for Shared<'g, T, R, N> { impl_trait!(shared); } //////////////////////////////////////////////////////////////////////////////////////////////////// // impl inherent //////////////////////////////////////////////////////////////////////////////////////////////////// impl<'g, T, R: Reclaim, N: Unsigned> Shared<'g, T, R, N> { impl_inherent!(shared); /// Decomposes the marked reference, returning the reference itself and the /// separated tag. #[inline] pub fn decompose_ref(shared: Self) -> (&'g T, usize) { let (ptr, tag) = shared.inner.decompose(); unsafe { (&*ptr.as_ptr(), tag) } } /// Consumes and decomposes the marked reference, returning only the /// reference itself. /// /// # Example /// /// Derefencing a [`Shared`] through the [`Deref`] implementation ties the /// returned reference to the shorter lifetime of the `shared` itself. /// Use this function to get a reference with the full lifetime `'g`. /// /// ``` /// use core::sync::atomic::Ordering::Relaxed; /// /// use reclaim::prelude::*; /// use reclaim::typenum::U0; /// use reclaim::leak::Shared; /// /// type Atomic<T> = reclaim::leak::Atomic<T, U0>; /// type Guard = reclaim::leak::Guard; /// /// let atomic = Atomic::new("string"); /// /// let mut guard = Guard::new(); /// let shared = atomic.load(Relaxed, &mut guard); /// /// let reference = Shared::into_ref(shared.unwrap()); /// assert_eq!(reference, &"string"); /// ``` #[inline] pub fn into_ref(shared: Self) -> &'g T { unsafe { &*shared.inner.decompose_ptr() } } /// Converts the `Shared` reference into an [`Unprotected`]. #[inline] pub fn into_unprotected(shared: Self) -> Unprotected<T, R, N> { Unprotected { inner: shared.inner, _marker: PhantomData } } /// Casts the [`Shared`] to a reference to a different type and with a different lifetime. /// /// This can be useful to extend the lifetime of a [`Shared`] in cases the borrow checker is /// unable to correctly determine the relationship between mutable borrows of guards and the /// resulting shared references. /// /// # Safety /// /// The caller has to ensure the cast is valid both in terms of type and lifetime. #[inline] pub unsafe fn cast<'h, U>(shared: Self) -> Shared<'h, U, R, N> { Shared { inner: shared.inner.cast(), _marker: PhantomData } } } //////////////////////////////////////////////////////////////////////////////////////////////////// // impl AsRef //////////////////////////////////////////////////////////////////////////////////////////////////// impl<'g, T, R: Reclaim, N: Unsigned> AsRef<T> for Shared<'g, T, R, N> { #[inline] fn as_ref(&self) -> &T { unsafe { self.inner.as_ref() } } } //////////////////////////////////////////////////////////////////////////////////////////////////// // impl Deref //////////////////////////////////////////////////////////////////////////////////////////////////// impl<'g, T, R: Reclaim, N: Unsigned> Deref for Shared<'g, T, R, N> { type Target = T; #[inline] fn deref(&self) -> &Self::Target { unsafe { self.inner.as_ref() } } } //////////////////////////////////////////////////////////////////////////////////////////////////// // impl Debug & Pointer //////////////////////////////////////////////////////////////////////////////////////////////////// impl<'g, T, R: Reclaim, N: Unsigned> fmt::Debug for Shared<'g, T, R, N> { #[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let (ptr, tag) = self.inner.decompose(); f.debug_struct("Shared").field("ptr", &ptr).field("tag", &tag).finish() } } impl<'g, T, R: Reclaim, N: Unsigned> fmt::Pointer for Shared<'g, T, R, N> { #[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Pointer::fmt(&self.inner.decompose_ptr(), f) } } //////////////////////////////////////////////////////////////////////////////////////////////////// // impl NonNullable //////////////////////////////////////////////////////////////////////////////////////////////////// impl<'g, T, R, N: Unsigned> NonNullable for Shared<'g, T, R, N> { type Item = T; type MarkBits = N; #[inline] fn into_marked_non_null(self) -> MarkedNonNull<Self::Item, Self::MarkBits> { self.inner } } //////////////////////////////////////////////////////////////////////////////////////////////////// // impl Internal //////////////////////////////////////////////////////////////////////////////////////////////////// impl<'g, T, R, N> Internal for Shared<'g, T, R, N> {}