1 | //! Sorted Linked List |
2 | |
3 | use std::{cell::Cell, cmp::Ordering, ptr}; |
4 | |
5 | use crate::utility_types::Delta; |
6 | pub(crate) unsafe trait Elem { |
7 | fn prev(&self) -> &Cell<*const Self>; |
8 | fn next(&self) -> &Cell<*const Self>; |
9 | fn key(&self) -> &Cell<u32>; |
10 | } |
11 | |
12 | pub(crate) enum AddToSllResult<'a, E: Elem> { |
13 | NoHead, |
14 | EmptyHead(&'a Cell<*const E>), |
15 | SmallerThanHead(&'a Cell<*const E>), |
16 | SmallerThanNotHead(*const E), |
17 | AlreadyInSll(*const E), |
18 | } |
19 | |
20 | impl<'a, E: Elem> AddToSllResult<'a, E> { |
21 | pub(crate) fn add_to_sll(&self, elem_ptr: *const E) { |
22 | unsafe { |
23 | (*elem_ptr).prev().set(elem_ptr); |
24 | (*elem_ptr).next().set(elem_ptr); |
25 | |
26 | match self { |
27 | // Case 1: empty head, replace it. |
28 | AddToSllResult::EmptyHead(head) => head.set(elem_ptr), |
29 | |
30 | // Case 2: we are smaller than the head, replace it. |
31 | AddToSllResult::SmallerThanHead(head) => { |
32 | let old_head = head.get(); |
33 | let prev = (*old_head).prev().replace(elem_ptr); |
34 | (*prev).next().set(elem_ptr); |
35 | (*elem_ptr).next().set(old_head); |
36 | (*elem_ptr).prev().set(prev); |
37 | head.set(elem_ptr); |
38 | } |
39 | |
40 | // Case 3: insert in place found by looping |
41 | AddToSllResult::SmallerThanNotHead(curr) => { |
42 | let next = (**curr).next().replace(elem_ptr); |
43 | (*next).prev().set(elem_ptr); |
44 | (*elem_ptr).prev().set(*curr); |
45 | (*elem_ptr).next().set(next); |
46 | } |
47 | AddToSllResult::NoHead | AddToSllResult::AlreadyInSll(_) => (), |
48 | } |
49 | } |
50 | } |
51 | } |
52 | |
53 | #[cold ] |
54 | pub(crate) fn init<'a, E: Elem>( |
55 | head: Option<&'a Cell<*const E>>, |
56 | elem: &E, |
57 | ) -> AddToSllResult<'a, E> { |
58 | if let Some(head: &Cell<*const E>) = head { |
59 | link(head, elem) |
60 | } else { |
61 | AddToSllResult::NoHead |
62 | } |
63 | } |
64 | |
65 | #[cold ] |
66 | pub(crate) fn unlink<E: Elem>(head: &Cell<*const E>, elem: &E) { |
67 | debug_assert!(!head.get().is_null(), "invalid linked list head" ); |
68 | |
69 | let elem_ptr: *const E = elem; |
70 | |
71 | let prev: *const E = elem.prev().replace(val:elem_ptr); |
72 | let next: *const E = elem.next().replace(val:elem_ptr); |
73 | unsafe { |
74 | debug_assert_eq!((*prev).next().get(), elem_ptr, "invalid linked list links" ); |
75 | debug_assert_eq!((*next).prev().get(), elem_ptr, "invalid linked list links" ); |
76 | (*prev).next().set(val:next); |
77 | (*next).prev().set(val:prev); |
78 | } |
79 | |
80 | if head.get() == elem_ptr { |
81 | head.set(val:if next == elem_ptr { ptr::null() } else { next }) |
82 | } |
83 | } |
84 | |
85 | #[cold ] |
86 | pub(crate) fn link<'a, E: Elem>(head: &'a Cell<*const E>, elem: &E) -> AddToSllResult<'a, E> { |
87 | unsafe { |
88 | let old_head = head.get(); |
89 | // Case 1: empty head, replace it. |
90 | if old_head.is_null() { |
91 | return AddToSllResult::EmptyHead(head); |
92 | } |
93 | |
94 | // Case 2: we are smaller than the head, replace it. |
95 | if elem.key() < (*old_head).key() { |
96 | return AddToSllResult::SmallerThanHead(head); |
97 | } |
98 | |
99 | // Case 3: loop *backward* until we find insertion place. Because of |
100 | // Case 2, we can't loop beyond the head. |
101 | let mut curr = (*old_head).prev().get(); |
102 | loop { |
103 | match (*curr).key().cmp(elem.key()) { |
104 | Ordering::Less => return AddToSllResult::SmallerThanNotHead(curr), |
105 | Ordering::Equal => return AddToSllResult::AlreadyInSll(curr), |
106 | Ordering::Greater => curr = (*curr).prev().get(), |
107 | } |
108 | } |
109 | } |
110 | } |
111 | |
112 | pub(crate) fn adjust<E: Elem>(elem: &E, from: u32, by: Delta<u32>) { |
113 | let elem_ptr: *const E = elem; |
114 | |
115 | unsafe { |
116 | let mut curr: *const E = elem_ptr; |
117 | loop { |
118 | let mut key: u32 = (*curr).key().get(); |
119 | if key >= from { |
120 | key += by; |
121 | (*curr).key().set(val:key); |
122 | } |
123 | curr = (*curr).next().get(); |
124 | if curr == elem_ptr { |
125 | break; |
126 | } |
127 | } |
128 | } |
129 | } |
130 | |