66
77use crate :: init:: PinInit ;
88use crate :: types:: Opaque ;
9+ use core:: marker:: PhantomData ;
910use core:: ptr;
1011
1112mod impl_list_item_mod;
@@ -14,7 +15,42 @@ pub use self::impl_list_item_mod::{impl_has_list_links, impl_list_item, HasListL
1415mod arc;
1516pub use self :: arc:: { impl_list_arc_safe, AtomicTracker , ListArc , ListArcSafe , TryNewListArc } ;
1617
17- /// Implemented by types where a [`ListArc<Self>`] can be inserted into a `List`.
18+ /// A linked list.
19+ ///
20+ /// All elements in this linked list will be [`ListArc`] references to the value. Since a value can
21+ /// only have one `ListArc` (for each pair of prev/next pointers), this ensures that the same
22+ /// prev/next pointers are not used for several linked lists.
23+ ///
24+ /// # Invariants
25+ ///
26+ /// * If the list is empty, then `first` is null. Otherwise, `first` points at the `ListLinks`
27+ /// field of the first element in the list.
28+ /// * All prev/next pointers in `ListLinks` fields of items in the list are valid and form a cycle.
29+ /// * For every item in the list, the list owns the associated [`ListArc`] reference and has
30+ /// exclusive access to the `ListLinks` field.
31+ pub struct List < T : ?Sized + ListItem < ID > , const ID : u64 = 0 > {
32+ first : * mut ListLinksFields ,
33+ _ty : PhantomData < ListArc < T , ID > > ,
34+ }
35+
36+ // SAFETY: This is a container of `ListArc<T, ID>`, and access to the container allows the same
37+ // type of access to the `ListArc<T, ID>` elements.
38+ unsafe impl < T , const ID : u64 > Send for List < T , ID >
39+ where
40+ ListArc < T , ID > : Send ,
41+ T : ?Sized + ListItem < ID > ,
42+ {
43+ }
44+ // SAFETY: This is a container of `ListArc<T, ID>`, and access to the container allows the same
45+ // type of access to the `ListArc<T, ID>` elements.
46+ unsafe impl < T , const ID : u64 > Sync for List < T , ID >
47+ where
48+ ListArc < T , ID > : Sync ,
49+ T : ?Sized + ListItem < ID > ,
50+ {
51+ }
52+
53+ /// Implemented by types where a [`ListArc<Self>`] can be inserted into a [`List`].
1854///
1955/// # Safety
2056///
@@ -56,7 +92,7 @@ pub unsafe trait ListItem<const ID: u64 = 0>: ListArcSafe<ID> {
5692 /// been called.
5793 unsafe fn view_value ( me : * mut ListLinks < ID > ) -> * const Self ;
5894
59- /// This is called when an item is inserted into a `List`.
95+ /// This is called when an item is inserted into a [ `List`] .
6096 ///
6197 /// # Guarantees
6298 ///
@@ -103,7 +139,6 @@ struct ListLinksFields {
103139pub struct ListLinks < const ID : u64 = 0 > {
104140 // This type is `!Unpin` for aliasing reasons as the pointers are part of an intrusive linked
105141 // list.
106- #[ allow( dead_code) ]
107142 inner : Opaque < ListLinksFields > ,
108143}
109144
@@ -127,4 +162,293 @@ impl<const ID: u64> ListLinks<ID> {
127162 } ) ,
128163 }
129164 }
165+
166+ /// # Safety
167+ ///
168+ /// `me` must be dereferenceable.
169+ #[ inline]
170+ unsafe fn fields ( me : * mut Self ) -> * mut ListLinksFields {
171+ // SAFETY: The caller promises that the pointer is valid.
172+ unsafe { Opaque :: raw_get ( ptr:: addr_of!( ( * me) . inner) ) }
173+ }
174+
175+ /// # Safety
176+ ///
177+ /// `me` must be dereferenceable.
178+ #[ inline]
179+ unsafe fn from_fields ( me : * mut ListLinksFields ) -> * mut Self {
180+ me. cast ( )
181+ }
182+ }
183+
184+ impl < T : ?Sized + ListItem < ID > , const ID : u64 > List < T , ID > {
185+ /// Creates a new empty list.
186+ pub const fn new ( ) -> Self {
187+ Self {
188+ first : ptr:: null_mut ( ) ,
189+ _ty : PhantomData ,
190+ }
191+ }
192+
193+ /// Returns whether this list is empty.
194+ pub fn is_empty ( & self ) -> bool {
195+ self . first . is_null ( )
196+ }
197+
198+ /// Add the provided item to the back of the list.
199+ pub fn push_back ( & mut self , item : ListArc < T , ID > ) {
200+ let raw_item = ListArc :: into_raw ( item) ;
201+ // SAFETY:
202+ // * We just got `raw_item` from a `ListArc`, so it's in an `Arc`.
203+ // * Since we have ownership of the `ListArc`, `post_remove` must have been called after
204+ // the most recent call to `prepare_to_insert`, if any.
205+ // * We own the `ListArc`.
206+ // * Removing items from this list is always done using `remove_internal_inner`, which
207+ // calls `post_remove` before giving up ownership.
208+ let list_links = unsafe { T :: prepare_to_insert ( raw_item) } ;
209+ // SAFETY: We have not yet called `post_remove`, so `list_links` is still valid.
210+ let item = unsafe { ListLinks :: fields ( list_links) } ;
211+
212+ if self . first . is_null ( ) {
213+ self . first = item;
214+ // SAFETY: The caller just gave us ownership of these fields.
215+ // INVARIANT: A linked list with one item should be cyclic.
216+ unsafe {
217+ ( * item) . next = item;
218+ ( * item) . prev = item;
219+ }
220+ } else {
221+ let next = self . first ;
222+ // SAFETY: By the type invariant, this pointer is valid or null. We just checked that
223+ // it's not null, so it must be valid.
224+ let prev = unsafe { ( * next) . prev } ;
225+ // SAFETY: Pointers in a linked list are never dangling, and the caller just gave us
226+ // ownership of the fields on `item`.
227+ // INVARIANT: This correctly inserts `item` between `prev` and `next`.
228+ unsafe {
229+ ( * item) . next = next;
230+ ( * item) . prev = prev;
231+ ( * prev) . next = item;
232+ ( * next) . prev = item;
233+ }
234+ }
235+ }
236+
237+ /// Add the provided item to the front of the list.
238+ pub fn push_front ( & mut self , item : ListArc < T , ID > ) {
239+ let raw_item = ListArc :: into_raw ( item) ;
240+ // SAFETY:
241+ // * We just got `raw_item` from a `ListArc`, so it's in an `Arc`.
242+ // * If this requirement is violated, then the previous caller of `prepare_to_insert`
243+ // violated the safety requirement that they can't give up ownership of the `ListArc`
244+ // until they call `post_remove`.
245+ // * We own the `ListArc`.
246+ // * Removing items] from this list is always done using `remove_internal_inner`, which
247+ // calls `post_remove` before giving up ownership.
248+ let list_links = unsafe { T :: prepare_to_insert ( raw_item) } ;
249+ // SAFETY: We have not yet called `post_remove`, so `list_links` is still valid.
250+ let item = unsafe { ListLinks :: fields ( list_links) } ;
251+
252+ if self . first . is_null ( ) {
253+ // SAFETY: The caller just gave us ownership of these fields.
254+ // INVARIANT: A linked list with one item should be cyclic.
255+ unsafe {
256+ ( * item) . next = item;
257+ ( * item) . prev = item;
258+ }
259+ } else {
260+ let next = self . first ;
261+ // SAFETY: We just checked that `next` is non-null.
262+ let prev = unsafe { ( * next) . prev } ;
263+ // SAFETY: Pointers in a linked list are never dangling, and the caller just gave us
264+ // ownership of the fields on `item`.
265+ // INVARIANT: This correctly inserts `item` between `prev` and `next`.
266+ unsafe {
267+ ( * item) . next = next;
268+ ( * item) . prev = prev;
269+ ( * prev) . next = item;
270+ ( * next) . prev = item;
271+ }
272+ }
273+ self . first = item;
274+ }
275+
276+ /// Removes the last item from this list.
277+ pub fn pop_back ( & mut self ) -> Option < ListArc < T , ID > > {
278+ if self . first . is_null ( ) {
279+ return None ;
280+ }
281+
282+ // SAFETY: We just checked that the list is not empty.
283+ let last = unsafe { ( * self . first ) . prev } ;
284+ // SAFETY: The last item of this list is in this list.
285+ Some ( unsafe { self . remove_internal ( last) } )
286+ }
287+
288+ /// Removes the first item from this list.
289+ pub fn pop_front ( & mut self ) -> Option < ListArc < T , ID > > {
290+ if self . first . is_null ( ) {
291+ return None ;
292+ }
293+
294+ // SAFETY: The first item of this list is in this list.
295+ Some ( unsafe { self . remove_internal ( self . first ) } )
296+ }
297+
298+ /// Removes the provided item from this list and returns it.
299+ ///
300+ /// This returns `None` if the item is not in the list. (Note that by the safety requirements,
301+ /// this means that the item is not in any list.)
302+ ///
303+ /// # Safety
304+ ///
305+ /// `item` must not be in a different linked list (with the same id).
306+ pub unsafe fn remove ( & mut self , item : & T ) -> Option < ListArc < T , ID > > {
307+ let mut item = unsafe { ListLinks :: fields ( T :: view_links ( item) ) } ;
308+ // SAFETY: The user provided a reference, and reference are never dangling.
309+ //
310+ // As for why this is not a data race, there are two cases:
311+ //
312+ // * If `item` is not in any list, then these fields are read-only and null.
313+ // * If `item` is in this list, then we have exclusive access to these fields since we
314+ // have a mutable reference to the list.
315+ //
316+ // In either case, there's no race.
317+ let ListLinksFields { next, prev } = unsafe { * item } ;
318+
319+ debug_assert_eq ! ( next. is_null( ) , prev. is_null( ) ) ;
320+ if !next. is_null ( ) {
321+ // This is really a no-op, but this ensures that `item` is a raw pointer that was
322+ // obtained without going through a pointer->reference->pointer conversion roundtrip.
323+ // This ensures that the list is valid under the more restrictive strict provenance
324+ // ruleset.
325+ //
326+ // SAFETY: We just checked that `next` is not null, and it's not dangling by the
327+ // list invariants.
328+ unsafe {
329+ debug_assert_eq ! ( item, ( * next) . prev) ;
330+ item = ( * next) . prev ;
331+ }
332+
333+ // SAFETY: We just checked that `item` is in a list, so the caller guarantees that it
334+ // is in this list. The pointers are in the right order.
335+ Some ( unsafe { self . remove_internal_inner ( item, next, prev) } )
336+ } else {
337+ None
338+ }
339+ }
340+
341+ /// Removes the provided item from the list.
342+ ///
343+ /// # Safety
344+ ///
345+ /// `item` must point at an item in this list.
346+ unsafe fn remove_internal ( & mut self , item : * mut ListLinksFields ) -> ListArc < T , ID > {
347+ // SAFETY: The caller promises that this pointer is not dangling, and there's no data race
348+ // since we have a mutable reference to the list containing `item`.
349+ let ListLinksFields { next, prev } = unsafe { * item } ;
350+ // SAFETY: The pointers are ok and in the right order.
351+ unsafe { self . remove_internal_inner ( item, next, prev) }
352+ }
353+
354+ /// Removes the provided item from the list.
355+ ///
356+ /// # Safety
357+ ///
358+ /// The `item` pointer must point at an item in this list, and we must have `(*item).next ==
359+ /// next` and `(*item).prev == prev`.
360+ unsafe fn remove_internal_inner (
361+ & mut self ,
362+ item : * mut ListLinksFields ,
363+ next : * mut ListLinksFields ,
364+ prev : * mut ListLinksFields ,
365+ ) -> ListArc < T , ID > {
366+ // SAFETY: We have exclusive access to the pointers of items in the list, and the prev/next
367+ // pointers are always valid for items in a list.
368+ //
369+ // INVARIANT: There are three cases:
370+ // * If the list has at least three items, then after removing the item, `prev` and `next`
371+ // will be next to each other.
372+ // * If the list has two items, then the remaining item will point at itself.
373+ // * If the list has one item, then `next == prev == item`, so these writes have no
374+ // effect. The list remains unchanged and `item` is still in the list for now.
375+ unsafe {
376+ ( * next) . prev = prev;
377+ ( * prev) . next = next;
378+ }
379+ // SAFETY: We have exclusive access to items in the list.
380+ // INVARIANT: `item` is being removed, so the pointers should be null.
381+ unsafe {
382+ ( * item) . prev = ptr:: null_mut ( ) ;
383+ ( * item) . next = ptr:: null_mut ( ) ;
384+ }
385+ // INVARIANT: There are three cases:
386+ // * If `item` was not the first item, then `self.first` should remain unchanged.
387+ // * If `item` was the first item and there is another item, then we just updated
388+ // `prev->next` to `next`, which is the new first item, and setting `item->next` to null
389+ // did not modify `prev->next`.
390+ // * If `item` was the only item in the list, then `prev == item`, and we just set
391+ // `item->next` to null, so this correctly sets `first` to null now that the list is
392+ // empty.
393+ if self . first == item {
394+ // SAFETY: The `prev` pointer is the value that `item->prev` had when it was in this
395+ // list, so it must be valid. There is no race since `prev` is still in the list and we
396+ // still have exclusive access to the list.
397+ self . first = unsafe { ( * prev) . next } ;
398+ }
399+
400+ // SAFETY: `item` used to be in the list, so it is dereferenceable by the type invariants
401+ // of `List`.
402+ let list_links = unsafe { ListLinks :: from_fields ( item) } ;
403+ // SAFETY: Any pointer in the list originates from a `prepare_to_insert` call.
404+ let raw_item = unsafe { T :: post_remove ( list_links) } ;
405+ // SAFETY: The above call to `post_remove` guarantees that we can recreate the `ListArc`.
406+ unsafe { ListArc :: from_raw ( raw_item) }
407+ }
408+
409+ /// Moves all items from `other` into `self`.
410+ ///
411+ /// The items of `other` are added to the back of `self`, so the last item of `other` becomes
412+ /// the last item of `self`.
413+ pub fn push_all_back ( & mut self , other : & mut List < T , ID > ) {
414+ // First, we insert the elements into `self`. At the end, we make `other` empty.
415+ if self . is_empty ( ) {
416+ // INVARIANT: All of the elements in `other` become elements of `self`.
417+ self . first = other. first ;
418+ } else if !other. is_empty ( ) {
419+ let other_first = other. first ;
420+ // SAFETY: The other list is not empty, so this pointer is valid.
421+ let other_last = unsafe { ( * other_first) . prev } ;
422+ let self_first = self . first ;
423+ // SAFETY: The self list is not empty, so this pointer is valid.
424+ let self_last = unsafe { ( * self_first) . prev } ;
425+
426+ // SAFETY: We have exclusive access to both lists, so we can update the pointers.
427+ // INVARIANT: This correctly sets the pointers to merge both lists. We do not need to
428+ // update `self.first` because the first element of `self` does not change.
429+ unsafe {
430+ ( * self_first) . prev = other_last;
431+ ( * other_last) . next = self_first;
432+ ( * self_last) . next = other_first;
433+ ( * other_first) . prev = self_last;
434+ }
435+ }
436+
437+ // INVARIANT: The other list is now empty, so update its pointer.
438+ other. first = ptr:: null_mut ( ) ;
439+ }
440+ }
441+
442+ impl < T : ?Sized + ListItem < ID > , const ID : u64 > Default for List < T , ID > {
443+ fn default ( ) -> Self {
444+ List :: new ( )
445+ }
446+ }
447+
448+ impl < T : ?Sized + ListItem < ID > , const ID : u64 > Drop for List < T , ID > {
449+ fn drop ( & mut self ) {
450+ while let Some ( item) = self . pop_front ( ) {
451+ drop ( item) ;
452+ }
453+ }
130454}
0 commit comments