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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
#![doc = include_str!("../README.md")]
#![cfg_attr(feature = "nightly", feature(generic_associated_types))]

use std::cell::Cell;
use std::marker::PhantomData;
use std::ops::Deref;
use std::ptr::null_mut;
use std::sync::Arc;

use parking_lot::{Mutex, MutexGuard};

type Inner = Arc<Mutex<*mut u8>>;

/// A `'static` handle through which a value with a covariant lifetime parameter can
/// temporarily be accessed.
///
/// `Lifelink<C>` implements [`Send`] and [`Sync`] when the wrapped values produced by
/// `C` are [`Send`].
///
/// See [`Lifelink::new`] for an example.
pub struct Lifelink<C: Ctor> {
    inner: Inner,
    _marker: PhantomData<C::Ty<'static>>,
}

// SAFETY: Inner is a Mutex, and `get` requires &mut self, so it's impossible to obtain
// multiple references to a Send-only type by Sending the Lifelink itself.
unsafe impl<C: SendCtor> Send for Lifelink<C> {}
unsafe impl<C: SendCtor> Sync for Lifelink<C> {}

/// Safe helper macro for creating a [`Lifelink`] value wrapping `thing`. The lifetime
/// of this [`Lifelink`] value will be managed by the Rust compiler, and the `thing`
/// passed in cannot be retrieved.
///
/// If you need a way to later retrieve ownership of the `thing` value passed in, see
/// the unsafe [`Lifelink::new`] constructor which this macro uses internally.
///
/// # Example
///
/// ```rust
/// use std::thread::spawn;
/// use std::sync::atomic::{AtomicUsize, Ordering};
/// use lifelink::{lifelink, Lifelink, RefCtor};
///
/// let answer = AtomicUsize::new(0);
///
/// lifelink!(lifelink: RefCtor<AtomicUsize> = &answer);
///
/// {
///     let guard = lifelink.get().unwrap();
///     assert_eq!(0, guard.load(Ordering::Relaxed));
///     guard.store(42, Ordering::Release);
/// }
///
/// assert_eq!(42, answer.load(Ordering::Acquire));
/// ```
#[macro_export]
macro_rules! lifelink {
    ($lifelink:ident : $ty:ty = $thing:expr) => {
        let (mut $lifelink, _deathtouch) = unsafe { $crate::Lifelink::<$ty>::new($thing) };
    };
}

impl<C: Ctor> Lifelink<C> {
    /// Create a pair of [`Lifelink`] and [`Deathtouch`] values wrapping `thing`, which
    /// will be kept alive and accessible through `Lifelink` until the [`Deathtouch`]
    /// is dropped.
    ///
    /// The safety of this function depends on the resulting [`Deathtouch`] value being
    /// unwrapped or dropped. For a safe way to construct [`Lifelink`] in exchange for
    /// the ability to access [`Deathtouch`], see the [`lifelink!`] macro.
    ///
    /// # Safety
    ///
    /// `C::Ty` values must be covariant over the lifetime parameter, and the resulting
    /// [`Deathtouch`] value must be unwrapped or dropped (i.e. not forgotten). For more
    /// details on the latter requirement, see https://github.com/chitoyuu/lifelink/issues/2.
    ///
    /// # Example
    ///
    /// ```rust
    /// use std::thread::spawn;
    /// use std::sync::atomic::{AtomicUsize, Ordering};
    /// use lifelink::{Lifelink, RefCtor};
    ///
    /// let answer = AtomicUsize::new(0);
    ///
    /// let (mut lifelink, deathtouch) = unsafe { Lifelink::<RefCtor<AtomicUsize>>::new(&answer) };
    ///
    /// {
    ///     let guard = lifelink.get().unwrap();
    ///     assert_eq!(0, guard.load(Ordering::Relaxed));
    ///     guard.store(42, Ordering::Release);
    /// }
    ///
    /// assert_eq!(42, deathtouch.unwrap().load(Ordering::Acquire));
    /// ```
    #[allow(clippy::needless_lifetimes)] // False positive
    pub unsafe fn new<'a>(thing: C::Ty<'a>) -> (Lifelink<C>, Deathtouch<'a, C>) {
        let thing = Box::new(thing);
        let ptr = Box::into_raw(thing) as *mut u8;
        let inner = Arc::new(Mutex::new(ptr));

        let lifelink = Lifelink {
            inner: Arc::clone(&inner),
            _marker: PhantomData,
        };

        let deathtouch = Deathtouch {
            inner,
            _marker: PhantomData,
        };

        (lifelink, deathtouch)
    }

    /// Returns a guard value that implements [`Deref`] to the wrapped value. Care must be taken
    /// to ensure that this value is dropped properly. Leaking the guard value may lead to a
    /// deadlock.
    pub fn get(&mut self) -> Option<Guard<'_, C>> {
        let lock = self.inner.lock();
        if lock.is_null() {
            None
        } else {
            Some(Guard {
                lock,
                _marker: PhantomData,
            })
        }
    }
}

/// A guard value that provides temporary access to the wrapped value. Care must be taken
/// to ensure that this value is dropped properly. Leaking the guard value may lead to a
/// deadlock.
///
/// `Guard<'_, C>` implements [`Send`] and [`Sync`] when the wrapped values produced by
/// `C` are [`Sync`].
pub struct Guard<'a, C: Ctor> {
    lock: MutexGuard<'a, *mut u8>,
    _marker: PhantomData<C::Ty<'static>>,
}

// SAFETY: Shared references are Send / Sync when and only when the value referred to is
// Sync.
unsafe impl<'a, C: SyncCtor> Send for Guard<'a, C> {}
unsafe impl<'a, C: SyncCtor> Sync for Guard<'a, C> {}

impl<'a, C> Deref for Guard<'a, C>
where
    C: Ctor + Cov,
{
    type Target = C::Ty<'a>;
    fn deref(&self) -> &Self::Target {
        let ptr: *mut u8 = *self.lock;
        // SAFETY: User promised so by implementing `Cov`.
        unsafe { &*(ptr as *const C::Ty<'a>) }
    }
}

/// A guard value that preserves compile-time lifetime information from the value passed
/// to [`Lifelink::new`].
///
/// This will block the calling thread when unwrapped or dropped, until all [`Guard`]s
/// currently alive go out of the scope. The value can then no longer be accessed from the
/// corresponding [`Lifelink`].
///
/// Note that Unlike `cryo`, this does *not* attempt to wait until the [`Lifelink`] handle
/// itself is dropped, only the [`Guard`] values it produces.  See the Caveats section of
/// README for more details.
pub struct Deathtouch<'a, C: Ctor> {
    inner: Inner,

    /// Invariant over 'a
    _marker: PhantomData<Cell<&'a C::Ty<'a>>>,
}

// SAFETY: The only public interfaces of this type takes `self`, and waits until there are
// no other Guards alive.
unsafe impl<'a, C: SendCtor> Send for Deathtouch<'a, C> {}

impl<'a, C: Ctor> Deathtouch<'a, C> {
    fn extract(&mut self) -> Option<C::Ty<'a>> {
        let mut lock = self.inner.lock();
        let ptr: *mut u8 = std::mem::replace(&mut *lock, null_mut());
        if ptr.is_null() {
            None
        } else {
            // SAFETY: this pointer is produced in Lifelink::new with Box::into_raw, and
            // the Deathtouch type itself is invariant over 'a
            unsafe { Some(*Box::from_raw(ptr as *mut C::Ty<'a>)) }
        }
    }

    /// Unwrap the contained value and return it. This will block until there is no
    /// other references to the value, so that compile-time lifetime invariants hold.
    ///
    /// See the module-level documentation for examples.
    pub fn unwrap(mut self) -> C::Ty<'a> {
        self.extract().unwrap()
    }
}

impl<'a, C: Ctor> Drop for Deathtouch<'a, C> {
    fn drop(&mut self) {
        self.extract();
    }
}

/// Trait for type constructors that take one single lifetime parameter. See also
/// [`Cov`] for [`Deref`] on [`Guard`].
pub trait Ctor {
    type Ty<'a>;
}

/// Trait for type constructors that produce types whose references are covariant over the
/// lifetime parameter.
///
/// For most valid types, this could implemented by simply invoking [`cov!`]:
///
/// ```rust
/// # use lifelink::*;
///
/// struct FooCtor;
/// struct Foo<'a>(&'a u8);
/// impl Ctor for FooCtor {
///     type Ty<'a> = Foo<'a>;
/// }
///
/// cov!(FooCtor);
/// ```
///
/// # Safety
///
/// References to types produced by this type constructor must be covariant over the lifetime
/// parameter.
///
/// This trait is `unsafe` for the reason that it is trivial to write a type-checking
/// implementation of `cov` for every type out there, simply by writing `panic!()`.
/// Lifetime variance is hard to figure out in a complex type. It's safest to use the [`cov!`]
/// macro for applicable types, unless you are really sure that you know better than the compiler.
pub unsafe trait Cov: Ctor {
    fn cov<'r, 'a, 'b>(r: &'r Self::Ty<'a>) -> &'r Self::Ty<'b>
    where
        'a: 'b;
}

/// Macro that implements [`Cov`] safely for a [`Ctor`] type.
///
/// [`Cov::cov`] is implemented by simply returning the input reference and letting Rust coerce it.
/// This should work automatically for most types that are actually covariant. In case `cov!(MyType)`
/// does not compile, users would need to provide their own `unsafe` [`Cov`] implementation.
///
/// See [`Cov`] for an example.
#[macro_export]
macro_rules! cov {
    (<$($tv:ident $(: $bound:tt $(+ $bounds:tt)*)?),*> $thing:ty) => {
        unsafe impl<$($tv $(: $bound $(+ $bounds)*)?),*> $crate::Cov for $thing {
            fn cov<'r, 'a, 'b>(r: &'r <Self as $crate::Ctor>::Ty<'a>) -> &'r <Self as $crate::Ctor>::Ty<'b>
            where
                'a: 'b,
            {
                r
            }
        }
    };

    ($thing:ty) => {
        $crate::cov!(<> $thing);
    };
}

/// Marker trait implemented for [`Ctor`]s where the constructed types are `Send`.
pub trait SendCtor: Ctor {}
impl<C> SendCtor for C
where
    C: Ctor,
    for<'a> C::Ty<'a>: Send,
{
}

/// Marker trait implemented for [`Ctor`]s where the constructed types are [`Sync`].
pub trait SyncCtor: Ctor {}
impl<C> SyncCtor for C
where
    C: Ctor,
    for<'a> C::Ty<'a>: Sync,
{
}

/// Constructor of references to `'static` values, that implements [`Ctor`] and [`Cov`].
///
/// This is provided for convenience, although if all you need is this, consider using the
/// [`cryo`](https://crates.io/crates/cryo) crate, which is much more mature and compiles on
/// stable today!
pub struct RefCtor<T> {
    _marker: PhantomData<T>,
}

impl<T: 'static> Ctor for RefCtor<T> {
    type Ty<'a> = &'a T;
}

cov!(<T: 'static> RefCtor<T>);

#[cfg(test)]
mod tests {
    use super::*;

    use std::sync::atomic::{AtomicUsize, Ordering};
    use std::time::Duration;

    #[test]
    fn local() {
        let answer = AtomicUsize::new(0);
        let mut leaked;

        {
            lifelink!(lifelink: RefCtor<AtomicUsize> = &answer);
            assert_eq!(
                Some(0),
                lifelink.get().map(|foo| foo.load(Ordering::Relaxed))
            );
            leaked = lifelink;
        }

        assert!(leaked.get().is_none());
    }

    #[test]
    fn sync() {
        use std::sync::mpsc::channel;
        use std::thread::spawn;

        let answer = AtomicUsize::new(0);

        lifelink!(lifelink: RefCtor<AtomicUsize> = &answer);
        let (send, recv) = channel();

        spawn(move || {
            let guard = lifelink.get().unwrap();
            assert_eq!(0, guard.load(Ordering::Relaxed));
            guard.store(42, Ordering::Release);
            send.send(()).unwrap();
        });

        recv.recv_timeout(Duration::from_millis(20)).unwrap();

        assert_eq!(42, answer.load(Ordering::Acquire));
    }
}