• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! Lock-free intrusive linked list.
2 //!
3 //! Ideas from Michael.  High Performance Dynamic Lock-Free Hash Tables and List-Based Sets.  SPAA
4 //! 2002.  <http://dl.acm.org/citation.cfm?id=564870.564881>
5 
6 use core::marker::PhantomData;
7 use core::sync::atomic::Ordering::{Acquire, Relaxed, Release};
8 
9 use crate::{unprotected, Atomic, Guard, Shared};
10 
11 /// An entry in a linked list.
12 ///
13 /// An Entry is accessed from multiple threads, so it would be beneficial to put it in a different
14 /// cache-line than thread-local data in terms of performance.
15 #[derive(Debug)]
16 pub(crate) struct Entry {
17     /// The next entry in the linked list.
18     /// If the tag is 1, this entry is marked as deleted.
19     next: Atomic<Entry>,
20 }
21 
22 /// Implementing this trait asserts that the type `T` can be used as an element in the intrusive
23 /// linked list defined in this module. `T` has to contain (or otherwise be linked to) an instance
24 /// of `Entry`.
25 ///
26 /// # Example
27 ///
28 /// ```ignore
29 /// struct A {
30 ///     entry: Entry,
31 ///     data: usize,
32 /// }
33 ///
34 /// impl IsElement<A> for A {
35 ///     fn entry_of(a: &A) -> &Entry {
36 ///         let entry_ptr = ((a as usize) + offset_of!(A, entry)) as *const Entry;
37 ///         unsafe { &*entry_ptr }
38 ///     }
39 ///
40 ///     unsafe fn element_of(entry: &Entry) -> &T {
41 ///         let elem_ptr = ((entry as usize) - offset_of!(A, entry)) as *const T;
42 ///         &*elem_ptr
43 ///     }
44 ///
45 ///     unsafe fn finalize(entry: &Entry, guard: &Guard) {
46 ///         guard.defer_destroy(Shared::from(Self::element_of(entry) as *const _));
47 ///     }
48 /// }
49 /// ```
50 ///
51 /// This trait is implemented on a type separate from `T` (although it can be just `T`), because
52 /// one type might be placeable into multiple lists, in which case it would require multiple
53 /// implementations of `IsElement`. In such cases, each struct implementing `IsElement<T>`
54 /// represents a distinct `Entry` in `T`.
55 ///
56 /// For example, we can insert the following struct into two lists using `entry1` for one
57 /// and `entry2` for the other:
58 ///
59 /// ```ignore
60 /// struct B {
61 ///     entry1: Entry,
62 ///     entry2: Entry,
63 ///     data: usize,
64 /// }
65 /// ```
66 ///
67 pub(crate) trait IsElement<T> {
68     /// Returns a reference to this element's `Entry`.
entry_of(_: &T) -> &Entry69     fn entry_of(_: &T) -> &Entry;
70 
71     /// Given a reference to an element's entry, returns that element.
72     ///
73     /// ```ignore
74     /// let elem = ListElement::new();
75     /// assert_eq!(elem.entry_of(),
76     ///            unsafe { ListElement::element_of(elem.entry_of()) } );
77     /// ```
78     ///
79     /// # Safety
80     ///
81     /// The caller has to guarantee that the `Entry` is called with was retrieved from an instance
82     /// of the element type (`T`).
element_of(_: &Entry) -> &T83     unsafe fn element_of(_: &Entry) -> &T;
84 
85     /// The function that is called when an entry is unlinked from list.
86     ///
87     /// # Safety
88     ///
89     /// The caller has to guarantee that the `Entry` is called with was retrieved from an instance
90     /// of the element type (`T`).
finalize(_: &Entry, _: &Guard)91     unsafe fn finalize(_: &Entry, _: &Guard);
92 }
93 
94 /// A lock-free, intrusive linked list of type `T`.
95 #[derive(Debug)]
96 pub(crate) struct List<T, C: IsElement<T> = T> {
97     /// The head of the linked list.
98     head: Atomic<Entry>,
99 
100     /// The phantom data for using `T` and `C`.
101     _marker: PhantomData<(T, C)>,
102 }
103 
104 /// An iterator used for retrieving values from the list.
105 pub(crate) struct Iter<'g, T, C: IsElement<T>> {
106     /// The guard that protects the iteration.
107     guard: &'g Guard,
108 
109     /// Pointer from the predecessor to the current entry.
110     pred: &'g Atomic<Entry>,
111 
112     /// The current entry.
113     curr: Shared<'g, Entry>,
114 
115     /// The list head, needed for restarting iteration.
116     head: &'g Atomic<Entry>,
117 
118     /// Logically, we store a borrow of an instance of `T` and
119     /// use the type information from `C`.
120     _marker: PhantomData<(&'g T, C)>,
121 }
122 
123 /// An error that occurs during iteration over the list.
124 #[derive(PartialEq, Debug)]
125 pub(crate) enum IterError {
126     /// A concurrent thread modified the state of the list at the same place that this iterator
127     /// was inspecting. Subsequent iteration will restart from the beginning of the list.
128     Stalled,
129 }
130 
131 impl Default for Entry {
132     /// Returns the empty entry.
default() -> Self133     fn default() -> Self {
134         Self {
135             next: Atomic::null(),
136         }
137     }
138 }
139 
140 impl Entry {
141     /// Marks this entry as deleted, deferring the actual deallocation to a later iteration.
142     ///
143     /// # Safety
144     ///
145     /// The entry should be a member of a linked list, and it should not have been deleted.
146     /// It should be safe to call `C::finalize` on the entry after the `guard` is dropped, where `C`
147     /// is the associated helper for the linked list.
delete(&self, guard: &Guard)148     pub(crate) unsafe fn delete(&self, guard: &Guard) {
149         self.next.fetch_or(1, Release, guard);
150     }
151 }
152 
153 impl<T, C: IsElement<T>> List<T, C> {
154     /// Returns a new, empty linked list.
new() -> Self155     pub(crate) fn new() -> Self {
156         Self {
157             head: Atomic::null(),
158             _marker: PhantomData,
159         }
160     }
161 
162     /// Inserts `entry` into the head of the list.
163     ///
164     /// # Safety
165     ///
166     /// You should guarantee that:
167     ///
168     /// - `container` is not null
169     /// - `container` is immovable, e.g. inside an `Owned`
170     /// - the same `Entry` is not inserted more than once
171     /// - the inserted object will be removed before the list is dropped
insert<'g>(&'g self, container: Shared<'g, T>, guard: &'g Guard)172     pub(crate) unsafe fn insert<'g>(&'g self, container: Shared<'g, T>, guard: &'g Guard) {
173         // Insert right after head, i.e. at the beginning of the list.
174         let to = &self.head;
175         // Get the intrusively stored Entry of the new element to insert.
176         let entry: &Entry = C::entry_of(container.deref());
177         // Make a Shared ptr to that Entry.
178         let entry_ptr = Shared::from(entry as *const _);
179         // Read the current successor of where we want to insert.
180         let mut next = to.load(Relaxed, guard);
181 
182         loop {
183             // Set the Entry of the to-be-inserted element to point to the previous successor of
184             // `to`.
185             entry.next.store(next, Relaxed);
186             match to.compare_exchange_weak(next, entry_ptr, Release, Relaxed, guard) {
187                 Ok(_) => break,
188                 // We lost the race or weak CAS failed spuriously. Update the successor and try
189                 // again.
190                 Err(err) => next = err.current,
191             }
192         }
193     }
194 
195     /// Returns an iterator over all objects.
196     ///
197     /// # Caveat
198     ///
199     /// Every object that is inserted at the moment this function is called and persists at least
200     /// until the end of iteration will be returned. Since this iterator traverses a lock-free
201     /// linked list that may be concurrently modified, some additional caveats apply:
202     ///
203     /// 1. If a new object is inserted during iteration, it may or may not be returned.
204     /// 2. If an object is deleted during iteration, it may or may not be returned.
205     /// 3. The iteration may be aborted when it lost in a race condition. In this case, the winning
206     ///    thread will continue to iterate over the same list.
iter<'g>(&'g self, guard: &'g Guard) -> Iter<'g, T, C>207     pub(crate) fn iter<'g>(&'g self, guard: &'g Guard) -> Iter<'g, T, C> {
208         Iter {
209             guard,
210             pred: &self.head,
211             curr: self.head.load(Acquire, guard),
212             head: &self.head,
213             _marker: PhantomData,
214         }
215     }
216 }
217 
218 impl<T, C: IsElement<T>> Drop for List<T, C> {
drop(&mut self)219     fn drop(&mut self) {
220         unsafe {
221             let guard = unprotected();
222             let mut curr = self.head.load(Relaxed, guard);
223             while let Some(c) = curr.as_ref() {
224                 let succ = c.next.load(Relaxed, guard);
225                 // Verify that all elements have been removed from the list.
226                 assert_eq!(succ.tag(), 1);
227 
228                 C::finalize(curr.deref(), guard);
229                 curr = succ;
230             }
231         }
232     }
233 }
234 
235 impl<'g, T: 'g, C: IsElement<T>> Iterator for Iter<'g, T, C> {
236     type Item = Result<&'g T, IterError>;
237 
next(&mut self) -> Option<Self::Item>238     fn next(&mut self) -> Option<Self::Item> {
239         while let Some(c) = unsafe { self.curr.as_ref() } {
240             let succ = c.next.load(Acquire, self.guard);
241 
242             if succ.tag() == 1 {
243                 // This entry was removed. Try unlinking it from the list.
244                 let succ = succ.with_tag(0);
245 
246                 // The tag should always be zero, because removing a node after a logically deleted
247                 // node leaves the list in an invalid state.
248                 debug_assert!(self.curr.tag() == 0);
249 
250                 // Try to unlink `curr` from the list, and get the new value of `self.pred`.
251                 let succ = match self
252                     .pred
253                     .compare_exchange(self.curr, succ, Acquire, Acquire, self.guard)
254                 {
255                     Ok(_) => {
256                         // We succeeded in unlinking `curr`, so we have to schedule
257                         // deallocation. Deferred drop is okay, because `list.delete()` can only be
258                         // called if `T: 'static`.
259                         unsafe {
260                             C::finalize(self.curr.deref(), self.guard);
261                         }
262 
263                         // `succ` is the new value of `self.pred`.
264                         succ
265                     }
266                     Err(e) => {
267                         // `e.current` is the current value of `self.pred`.
268                         e.current
269                     }
270                 };
271 
272                 // If the predecessor node is already marked as deleted, we need to restart from
273                 // `head`.
274                 if succ.tag() != 0 {
275                     self.pred = self.head;
276                     self.curr = self.head.load(Acquire, self.guard);
277 
278                     return Some(Err(IterError::Stalled));
279                 }
280 
281                 // Move over the removed by only advancing `curr`, not `pred`.
282                 self.curr = succ;
283                 continue;
284             }
285 
286             // Move one step forward.
287             self.pred = &c.next;
288             self.curr = succ;
289 
290             return Some(Ok(unsafe { C::element_of(c) }));
291         }
292 
293         // We reached the end of the list.
294         None
295     }
296 }
297 
298 #[cfg(all(test, not(crossbeam_loom)))]
299 mod tests {
300     use super::*;
301     use crate::{Collector, Owned};
302     use crossbeam_utils::thread;
303     use std::sync::Barrier;
304 
305     impl IsElement<Entry> for Entry {
entry_of(entry: &Entry) -> &Entry306         fn entry_of(entry: &Entry) -> &Entry {
307             entry
308         }
309 
element_of(entry: &Entry) -> &Entry310         unsafe fn element_of(entry: &Entry) -> &Entry {
311             entry
312         }
313 
finalize(entry: &Entry, guard: &Guard)314         unsafe fn finalize(entry: &Entry, guard: &Guard) {
315             guard.defer_destroy(Shared::from(Self::element_of(entry) as *const _));
316         }
317     }
318 
319     /// Checks whether the list retains inserted elements
320     /// and returns them in the correct order.
321     #[test]
insert()322     fn insert() {
323         let collector = Collector::new();
324         let handle = collector.register();
325         let guard = handle.pin();
326 
327         let l: List<Entry> = List::new();
328 
329         let e1 = Owned::new(Entry::default()).into_shared(&guard);
330         let e2 = Owned::new(Entry::default()).into_shared(&guard);
331         let e3 = Owned::new(Entry::default()).into_shared(&guard);
332 
333         unsafe {
334             l.insert(e1, &guard);
335             l.insert(e2, &guard);
336             l.insert(e3, &guard);
337         }
338 
339         let mut iter = l.iter(&guard);
340         let maybe_e3 = iter.next();
341         assert!(maybe_e3.is_some());
342         assert!(maybe_e3.unwrap().unwrap() as *const Entry == e3.as_raw());
343         let maybe_e2 = iter.next();
344         assert!(maybe_e2.is_some());
345         assert!(maybe_e2.unwrap().unwrap() as *const Entry == e2.as_raw());
346         let maybe_e1 = iter.next();
347         assert!(maybe_e1.is_some());
348         assert!(maybe_e1.unwrap().unwrap() as *const Entry == e1.as_raw());
349         assert!(iter.next().is_none());
350 
351         unsafe {
352             e1.as_ref().unwrap().delete(&guard);
353             e2.as_ref().unwrap().delete(&guard);
354             e3.as_ref().unwrap().delete(&guard);
355         }
356     }
357 
358     /// Checks whether elements can be removed from the list and whether
359     /// the correct elements are removed.
360     #[test]
delete()361     fn delete() {
362         let collector = Collector::new();
363         let handle = collector.register();
364         let guard = handle.pin();
365 
366         let l: List<Entry> = List::new();
367 
368         let e1 = Owned::new(Entry::default()).into_shared(&guard);
369         let e2 = Owned::new(Entry::default()).into_shared(&guard);
370         let e3 = Owned::new(Entry::default()).into_shared(&guard);
371         unsafe {
372             l.insert(e1, &guard);
373             l.insert(e2, &guard);
374             l.insert(e3, &guard);
375             e2.as_ref().unwrap().delete(&guard);
376         }
377 
378         let mut iter = l.iter(&guard);
379         let maybe_e3 = iter.next();
380         assert!(maybe_e3.is_some());
381         assert!(maybe_e3.unwrap().unwrap() as *const Entry == e3.as_raw());
382         let maybe_e1 = iter.next();
383         assert!(maybe_e1.is_some());
384         assert!(maybe_e1.unwrap().unwrap() as *const Entry == e1.as_raw());
385         assert!(iter.next().is_none());
386 
387         unsafe {
388             e1.as_ref().unwrap().delete(&guard);
389             e3.as_ref().unwrap().delete(&guard);
390         }
391 
392         let mut iter = l.iter(&guard);
393         assert!(iter.next().is_none());
394     }
395 
396     const THREADS: usize = 8;
397     const ITERS: usize = 512;
398 
399     /// Contends the list on insert and delete operations to make sure they can run concurrently.
400     #[test]
insert_delete_multi()401     fn insert_delete_multi() {
402         let collector = Collector::new();
403 
404         let l: List<Entry> = List::new();
405         let b = Barrier::new(THREADS);
406 
407         thread::scope(|s| {
408             for _ in 0..THREADS {
409                 s.spawn(|_| {
410                     b.wait();
411 
412                     let handle = collector.register();
413                     let guard: Guard = handle.pin();
414                     let mut v = Vec::with_capacity(ITERS);
415 
416                     for _ in 0..ITERS {
417                         let e = Owned::new(Entry::default()).into_shared(&guard);
418                         v.push(e);
419                         unsafe {
420                             l.insert(e, &guard);
421                         }
422                     }
423 
424                     for e in v {
425                         unsafe {
426                             e.as_ref().unwrap().delete(&guard);
427                         }
428                     }
429                 });
430             }
431         })
432         .unwrap();
433 
434         let handle = collector.register();
435         let guard = handle.pin();
436 
437         let mut iter = l.iter(&guard);
438         assert!(iter.next().is_none());
439     }
440 
441     /// Contends the list on iteration to make sure that it can be iterated over concurrently.
442     #[test]
iter_multi()443     fn iter_multi() {
444         let collector = Collector::new();
445 
446         let l: List<Entry> = List::new();
447         let b = Barrier::new(THREADS);
448 
449         thread::scope(|s| {
450             for _ in 0..THREADS {
451                 s.spawn(|_| {
452                     b.wait();
453 
454                     let handle = collector.register();
455                     let guard: Guard = handle.pin();
456                     let mut v = Vec::with_capacity(ITERS);
457 
458                     for _ in 0..ITERS {
459                         let e = Owned::new(Entry::default()).into_shared(&guard);
460                         v.push(e);
461                         unsafe {
462                             l.insert(e, &guard);
463                         }
464                     }
465 
466                     let mut iter = l.iter(&guard);
467                     for _ in 0..ITERS {
468                         assert!(iter.next().is_some());
469                     }
470 
471                     for e in v {
472                         unsafe {
473                             e.as_ref().unwrap().delete(&guard);
474                         }
475                     }
476                 });
477             }
478         })
479         .unwrap();
480 
481         let handle = collector.register();
482         let guard = handle.pin();
483 
484         let mut iter = l.iter(&guard);
485         assert!(iter.next().is_none());
486     }
487 }
488