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
use UnsafeCell;
use crate::;
pub
/// Locks a collection of locks, which cannot be shared immutably.
///
/// This could be a tuple of [`Lockable`] types, an array, or a `Vec`. But it
/// can be safely locked without causing a deadlock.
///
/// The data in this collection is guaranteed to not contain duplicates because
/// `L` must always implement [`OwnedLockable`]. The underlying data may not be
/// immutably referenced. Because of this, there is no need for sorting the
/// locks in the collection, or checking for duplicates, because it can be
/// guaranteed that until the underlying collection is mutated (which requires
/// releasing all acquired locks in the collection to do), then the locks will
/// stay in the same order and be locked in that order, preventing cyclic wait.
///
/// [`Lockable`]: `crate::lockable::Lockable`
/// [`OwnedLockable`]: `crate::lockable::OwnedLockable`
// this type caches the idea that no immutable references to the underlying
// collection exist
/// Locks a reference to a collection of locks, by sorting them by memory
/// address.
///
/// This could be a tuple of [`Lockable`] types, an array, or a `Vec`. But it
/// can be safely locked without causing a deadlock.
///
/// Upon construction, it must be confirmed that the collection contains no
/// duplicate locks. This can be done by either using [`OwnedLockable`] or by
/// checking. Regardless of how this is done, the locks will be sorted by their
/// memory address before locking them. The sorted order of the locks is cached
/// within this collection.
///
/// Unlike [`BoxedLockCollection`], this type does not allocate memory for the
/// data, although it does allocate memory for the sorted list of lock
/// references. This makes it slightly faster, but lifetimes must be handled.
///
/// [`Lockable`]: `crate::lockable::Lockable`
/// [`OwnedLockable`]: `crate::lockable::OwnedLockable`
//
// This type was born when I eventually realized that I needed a self
// referential structure. That used boxing, so I elected to make a more
// efficient implementation (polonius please save us)
//
// This type caches the sorting order of the locks and the fact that it doesn't
// contain any duplicates.
/// Locks a collection of locks, stored in the heap, by sorting them by memory
/// address.
///
/// This could be a tuple of [`Lockable`] types, an array, or a `Vec`. But it
/// can be safely locked without causing a deadlock.
///
/// Upon construction, it must be confirmed that the collection contains no
/// duplicate locks. This can be done by either using [`OwnedLockable`] or by
/// checking. Regardless of how this is done, the locks will be sorted by their
/// memory address before locking them. The sorted order of the locks is cached
/// within this collection.
///
/// Unlike [`RefLockCollection`], this is a self-referential type which boxes
/// the data that is given to it. This means no lifetimes are necessary on the
/// type itself, but it is slightly slower because of the memory allocation.
///
/// [`Lockable`]: `crate::lockable::Lockable`
/// [`OwnedLockable`]: `crate::lockable::OwnedLockable`
//
// This type caches the sorting order of the locks and the fact that it doesn't
// contain any duplicates.
/// Locks a collection of locks using a retrying algorithm.
///
/// This could be a tuple of [`Lockable`] types, an array, or a `Vec`. But it
/// can be safely locked without causing a deadlock.
///
/// The data in this collection is guaranteed to not contain duplicates, but it
/// also is not sorted. In some cases the lack of sorting can increase
/// performance. However, in most cases, this collection will be slower. Cyclic
/// wait is not guaranteed here, so the locking algorithm must release all its
/// locks if one of the lock attempts blocks. This results in wasted time and
/// potential [livelocking].
///
/// However, one case where this might be faster than [`RefLockCollection`] is
/// when cyclic wait is ensured manually. This will prevent the need for
/// subsequent unlocking and re-locking.
///
/// [`Lockable`]: `crate::lockable::Lockable`
/// [`OwnedLockable`]: `crate::lockable::OwnedLockable`
/// [livelocking]: https://en.wikipedia.org/wiki/Deadlock#Livelock
//
// This type caches the fact that there are no duplicates
/// A RAII guard for a generic [`Lockable`] type. When this structure is
/// dropped (falls out of scope), the locks will be unlocked.
///
/// The data protected by the mutex can be accessed through this guard via its
/// [`Deref`] and [`DerefMut`] implementations.
///
/// Several lock collections can be used to create this type. Specifically,
/// [`BoxedLockCollection`], [`RefLockCollection`], [`OwnedLockCollection`], and
/// [`RetryingLockCollection`]. It is created using the methods, `lock`,
/// `try_lock`, `read`, and `try_read`.
///
/// [`Deref`]: `std::ops::Deref`
/// [`DerefMut`]: `std::ops::DerefMut`
/// [`Lockable`]: `crate::lockable::Lockable`