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
//! Lifetime-branded tokens (a.k.a. GhostCell)
use crate::;
pub use crate*;
/// Lifetime-branded tag for use with [`SingletonToken`].
///
/// This type is invariant over `'brand`, although this could be just covariant
/// without loss of soundness.
/// Lifetime-branded token that can be used to access the contents of a
/// `TokenLock<T, `[`BrandedTokenId`]`<'brand>>`.
/// Created by [`with_branded_token`].
///
/// See [`with_branded_token`] for an example.
pub type BrandedToken<'brand> = ;
/// Zero-sized logical equivalent of `&'a `[`BrandedToken`]`<'brand>`.
pub type BrandedTokenRef<'a, 'brand> = ;
/// Zero-sized logical equivalent of `&'a mut `[`BrandedToken`]`<'brand>`.
pub type BrandedTokenRefMut<'a, 'brand> = ;
/// The `!Sync` variant of [`BrandedToken`].
pub type UnsyncBrandedToken<'brand> = ;
/// Zero-sized logical equivalent of `&'a `[`UnsyncBrandedToken`]`<'brand>`.
/// The `!Sync` variant of [`BrandedTokenRef`].
pub type UnsyncBrandedTokenRef<'a, 'brand> = ;
/// Zero-sized logical equivalent of `&'a mut `[`UnsyncBrandedToken`]`<'brand>`.
/// The `!Sync` variant of [`BrandedTokenRefMut`].
pub type UnsyncBrandedTokenRefMut<'a, 'brand> = ;
/// Lifetime-branded token that cannot be used to access the contents of a
/// `TokenLock<T, `[`BrandedTokenId`]`<'brand>>` but can be used to create one.
/// Can be `default`-constructed.
pub type BrandedTokenId<'brand> = ;
/// A mutual exclusive primitive that can be accessed by presenting a
/// [`BrandedToken`] with the correct brand lifetime parameter.
pub type BrandedTokenLock<'brand, T> = ;
/// A [pinned] mutual exclusive primitive that can be accessed by presenting a
/// [`BrandedToken`] with the correct brand lifetime parameter.
///
/// [pinned]: core::pin
pub type BrandedPinTokenLock<'brand, T> = ;
/// Like [`BrandedTokenLock`] but requires presenting [`UnsyncBrandedToken`],
/// which is [`Unsync`]. This subtle difference allows it to be `Sync` even if
/// `T` is not.
///
/// [`Unsync`]: crate::Unsync
pub type UnsyncBrandedTokenLock<'brand, T> = ;
/// Like [`BrandedPinTokenLock`] but requires presenting [`UnsyncBrandedToken`],
/// which is [`Unsync`]. This subtle difference allows it to be `Sync` even if
/// `T` is not.
///
/// [`Unsync`]: crate::Unsync
pub type UnsyncBrandedPinTokenLock<'brand, T> = ;
/// Call the provided closure with a brand new [`BrandedToken`], which can
/// only be used throughout the duration of the function call.
///
/// This pattern is known as [GhostCell][1] and has been formally proven for
/// soundness (excluding the extensions provided by this crate).
///
/// [1]: http://plv.mpi-sws.org/rustbelt/ghostcell/
///
/// # Example
///
/// ```rust,edition2018
/// use rayon::prelude::*;
/// use tokenlock::{with_branded_token, BrandedTokenLock};
///
/// struct Node<'arena, 'brand> {
/// next: BrandedTokenLock<'brand, Option<&'arena Node<'arena, 'brand>>>,
/// }
///
/// with_branded_token(|mut token| {
/// let arena = [
/// Node { next: BrandedTokenLock::wrap(None) },
/// Node { next: BrandedTokenLock::wrap(None) },
/// // The above is equivalent to:
/// // Node { next: BrandedTokenLock::new(Default::default(), None) },
/// ];
///
/// // Link the nodes together
/// arena[0].next.replace(&mut token, Some(&arena[1]));
/// arena[1].next.replace(&mut token, Some(&arena[0]));
///
/// // Unlike `Cell`, this doesn't prevent shared read-only access
/// arena.par_iter().for_each(|item| {
/// println!("{:p} is linked to {:p}", item, item.next.get(&token).unwrap());
/// });
/// });
/// ```
///
/// ```rust,edition2018
/// use rayon::prelude::*;
/// use std::sync::mpsc;
/// use tokenlock::{with_branded_token, UnsyncBrandedTokenLock};
///
/// with_branded_token(|mut token| {
/// let unsync_token = token.borrow_unsync_mut();
///
/// let senders: Vec<_> = (0..4)
/// .map(|_| UnsyncBrandedTokenLock::wrap(mpsc::channel().0))
/// .collect();
///
/// // `unsync_token` unlocks `UnsyncBrandedTokenLock`
/// let _ = senders[0].read(&*unsync_token).send(());
///
/// // `Sender` is `!Sync`, but that doesn't make `senders` `!Sync` because
/// // `UnsyncBrandedTokenLock` can only be borrowed by one thread at the
/// // same time
/// senders.par_iter().for_each(|item| println!("{:p}", item));
/// });
/// ```