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> {}