lock_free/
skiplist_fast.rs1use std::sync::atomic::{AtomicPtr, AtomicU64, Ordering};
10use std::ptr::{self, null_mut};
11use std::cmp::Ordering as CmpOrdering;
12use std::cell::Cell;
13
14const MAX_HEIGHT: usize = 16; const PROBABILITY: u32 = 0x80000000; thread_local! {
18 static RNG: Cell<u64> = Cell::new({
20 let mut hasher = std::collections::hash_map::DefaultHasher::new();
21 std::hash::Hash::hash(&std::thread::current().id(), &mut hasher);
22 std::hash::Hasher::finish(&hasher)
23 });
24}
25
26#[inline]
27fn fast_random() -> u32 {
28 RNG.with(|rng| {
29 let mut x = rng.get();
31 x ^= x << 13;
32 x ^= x >> 7;
33 x ^= x << 17;
34 rng.set(x);
35 (x >> 32) as u32
36 })
37}
38
39#[inline]
40fn random_height() -> usize {
41 let mut height = 1;
42 while height < MAX_HEIGHT && fast_random() < PROBABILITY {
43 height += 1;
44 }
45 height
46}
47
48#[repr(align(64))]
50struct Node<K, V> {
51 key: K,
52 value: V,
53 height: usize,
54 next: [AtomicPtr<Node<K, V>>; MAX_HEIGHT],
55}
56
57impl<K, V> Node<K, V> {
58 fn new(key: K, value: V, height: usize) -> Box<Self> {
59 let mut node = Box::new(Node {
60 key,
61 value,
62 height,
63 next: unsafe { std::mem::zeroed() },
64 });
65
66 for i in 0..MAX_HEIGHT {
68 node.next[i] = AtomicPtr::new(null_mut());
69 }
70
71 node
72 }
73}
74
75pub struct FastSkipList<K, V> {
77 head: Box<Node<K, V>>,
78 size: AtomicU64,
79}
80
81impl<K: Ord + Default, V: Default> FastSkipList<K, V> {
82 pub fn new() -> Self {
84 let head = Node::new(K::default(), V::default(), MAX_HEIGHT);
85 Self {
86 head,
87 size: AtomicU64::new(0),
88 }
89 }
90
91 #[inline]
93 fn find(&self, key: &K) -> ([*mut Node<K, V>; MAX_HEIGHT], [*mut Node<K, V>; MAX_HEIGHT]) {
94 let mut preds: [*mut Node<K, V>; MAX_HEIGHT] = [null_mut(); MAX_HEIGHT];
95 let mut succs: [*mut Node<K, V>; MAX_HEIGHT] = [null_mut(); MAX_HEIGHT];
96
97 let mut current = &*self.head as *const Node<K, V> as *mut Node<K, V>;
98
99 for level in (0..MAX_HEIGHT).rev() {
100 loop {
101 let next = unsafe { (*current).next[level].load(Ordering::Acquire) };
102
103 if next.is_null() {
104 break;
105 }
106
107 let next_key = unsafe { &(*next).key };
108 if next_key < key {
109 current = next;
110 } else {
111 break;
112 }
113 }
114
115 preds[level] = current;
116 succs[level] = unsafe { (*current).next[level].load(Ordering::Acquire) };
117 }
118
119 (preds, succs)
120 }
121
122 pub fn insert(&self, key: K, value: V) -> bool {
124 let height = random_height();
125 let new_node = Box::into_raw(Node::new(key, value, height));
126
127 loop {
128 let (mut preds, mut succs) = self.find(unsafe { &(*new_node).key });
129
130 if !succs[0].is_null() {
132 let succ_key = unsafe { &(*succs[0]).key };
133 if succ_key == unsafe { &(*new_node).key } {
134 unsafe { Box::from_raw(new_node); }
136 return false;
137 }
138 }
139
140 for level in 0..height {
142 unsafe {
143 (*new_node).next[level].store(succs[level], Ordering::Relaxed);
144 }
145 }
146
147 let pred_next = unsafe { &(*preds[0]).next[0] };
149 match pred_next.compare_exchange(
150 succs[0],
151 new_node,
152 Ordering::Release,
153 Ordering::Acquire
154 ) {
155 Ok(_) => {
156 for level in 1..height {
158 loop {
159 let pred_next = unsafe { &(*preds[level]).next[level] };
160 match pred_next.compare_exchange(
161 succs[level],
162 new_node,
163 Ordering::Release,
164 Ordering::Acquire
165 ) {
166 Ok(_) => break,
167 Err(_) => {
168 let (new_preds, new_succs) = self.find(unsafe { &(*new_node).key });
170 preds[level] = new_preds[level];
171 succs[level] = new_succs[level];
172 }
173 }
174 }
175 }
176
177 self.size.fetch_add(1, Ordering::Relaxed);
178 return true;
179 }
180 Err(_) => {
181 continue;
183 }
184 }
185 }
186 }
187
188 pub fn contains(&self, key: &K) -> bool {
190 let mut current = &*self.head as *const Node<K, V> as *mut Node<K, V>;
191
192 for level in (0..MAX_HEIGHT).rev() {
194 loop {
195 let next = unsafe { (*current).next[level].load(Ordering::Acquire) };
196
197 if next.is_null() {
198 break;
199 }
200
201 let next_key = unsafe { &(*next).key };
202 match next_key.cmp(key) {
203 CmpOrdering::Less => current = next,
204 CmpOrdering::Equal => return true,
205 CmpOrdering::Greater => break,
206 }
207 }
208 }
209
210 false
211 }
212
213 pub fn get(&self, key: &K) -> Option<*const V> {
215 let mut current = &*self.head as *const Node<K, V> as *mut Node<K, V>;
216
217 for level in (0..MAX_HEIGHT).rev() {
218 loop {
219 let next = unsafe { (*current).next[level].load(Ordering::Acquire) };
220
221 if next.is_null() {
222 break;
223 }
224
225 let next_key = unsafe { &(*next).key };
226 match next_key.cmp(key) {
227 CmpOrdering::Less => current = next,
228 CmpOrdering::Equal => {
229 return Some(unsafe { &(*next).value as *const V });
230 }
231 CmpOrdering::Greater => break,
232 }
233 }
234 }
235
236 None
237 }
238
239 pub fn remove(&self, key: &K) -> bool {
241 let (mut preds, succs) = self.find(key);
242
243 if succs[0].is_null() {
245 return false;
246 }
247
248 let node_key = unsafe { &(*succs[0]).key };
249 if node_key != key {
250 return false;
251 }
252
253 let node = succs[0];
254 let height = unsafe { (*node).height };
255
256 for level in (0..height).rev() {
258 loop {
259 let next = unsafe { (*node).next[level].load(Ordering::Acquire) };
260 let pred_next = unsafe { &(*preds[level]).next[level] };
261
262 match pred_next.compare_exchange(
263 node,
264 next,
265 Ordering::Release,
266 Ordering::Acquire
267 ) {
268 Ok(_) => break,
269 Err(_) => {
270 let (new_preds, _) = self.find(key);
272 preds[level] = new_preds[level];
273 }
274 }
275 }
276 }
277
278 unsafe { Box::from_raw(node); }
280 self.size.fetch_sub(1, Ordering::Relaxed);
281 true
282 }
283
284 pub fn len(&self) -> usize {
286 self.size.load(Ordering::Relaxed) as usize
287 }
288}
289
290unsafe impl<K: Send, V: Send> Send for FastSkipList<K, V> {}
291unsafe impl<K: Send + Sync, V: Send + Sync> Sync for FastSkipList<K, V> {}
292
293impl<K, V> Drop for FastSkipList<K, V> {
294 fn drop(&mut self) {
295 let mut current = self.head.next[0].load(Ordering::Acquire);
296
297 while !current.is_null() {
298 let next = unsafe {
299 let node = Box::from_raw(current);
300 node.next[0].load(Ordering::Acquire)
301 };
302 current = next;
303 }
304 }
305}