1#![warn(unsafe_op_in_unsafe_fn)]
6
7use fuchsia_rcu::subtle::{RcuPtr, RcuPtrRef};
8use fuchsia_rcu::{RcuReadScope, rcu_drop};
9
10use crate::rcu_intrusive_list::{Link, RcuIntrusiveList, RcuIntrusiveListCursor, RcuListAdapter};
11
12#[derive(Debug)]
22pub struct RcuList<T: Send + Sync + 'static, A: RcuListAdapter<T>> {
23 list: RcuIntrusiveList<T, A>,
24}
25
26impl<T: Send + Sync + 'static, A: RcuListAdapter<T>> Default for RcuList<T, A> {
27 fn default() -> Self {
28 Self { list: RcuIntrusiveList::default() }
29 }
30}
31
32impl<T: Send + Sync + 'static, A: RcuListAdapter<T>> RcuList<T, A> {
33 pub fn new(head: RcuPtr<Link>, tail: RcuPtr<Link>) -> Self {
35 Self { list: RcuIntrusiveList::new(head, tail) }
36 }
37
38 pub unsafe fn push_front<'a>(&self, scope: &'a RcuReadScope, data: T) -> RcuPtrRef<'a, T> {
44 let node = alloc(scope, data);
45 unsafe {
47 self.list.push_front(scope, node);
48 }
49 node
50 }
51
52 pub unsafe fn push_back<'a>(&self, scope: &'a RcuReadScope, data: T) -> RcuPtrRef<'a, T> {
58 let node = alloc(scope, data);
59 unsafe {
61 self.list.push_back(scope, node);
62 }
63 node
64 }
65
66 pub unsafe fn append(&self, scope: &RcuReadScope, other: Self) {
72 unsafe {
74 let items = other.list.split_off(scope, 0);
75 self.list.append(scope, items);
76 }
77 }
78
79 pub unsafe fn split_off(&self, scope: &RcuReadScope, pos: usize) -> Self {
87 Self { list: unsafe { self.list.split_off(scope, pos) } }
89 }
90
91 pub unsafe fn clear(&self) {
100 let scope = RcuReadScope::new();
101 unsafe { self.list.clear(&scope, deferred_dealloc) };
103 }
104
105 #[cfg(test)]
106 fn is_empty(&self) -> bool {
107 let scope = RcuReadScope::new();
108 self.list.is_empty(&scope)
109 }
110
111 pub fn cursor<'a>(&'a self, scope: &'a RcuReadScope) -> RcuListCursor<'a, T, A> {
116 RcuListCursor { cursor: self.list.cursor(scope) }
117 }
118
119 pub fn iter<'a>(&self, scope: &'a RcuReadScope) -> impl Iterator<Item = &'a T> {
121 self.list.iter(scope)
122 }
123}
124
125fn alloc<T>(scope: &RcuReadScope, data: T) -> RcuPtrRef<'_, T> {
129 let ptr = Box::into_raw(Box::new(data));
130 unsafe { RcuPtrRef::new(scope, ptr) }
133}
134
135fn deferred_dealloc<T>(node: RcuPtrRef<'_, T>)
139where
140 T: Send + Sync + 'static,
141{
142 let value = unsafe { Box::from_raw(node.as_mut_ptr()) };
144 rcu_drop(value);
145}
146
147pub struct RcuListCursor<'a, T: Send + Sync + 'static, A: RcuListAdapter<T>> {
148 cursor: RcuIntrusiveListCursor<'a, T, A>,
149}
150
151impl<'a, T: Send + Sync + 'static, A: RcuListAdapter<T>> RcuListCursor<'a, T, A> {
152 pub fn current(&self) -> Option<&T> {
154 self.cursor.current()
155 }
156
157 pub fn advance(&mut self) {
159 self.cursor.advance();
160 }
161
162 pub unsafe fn remove(&mut self) -> RcuPtrRef<'a, T> {
173 let removed = unsafe { self.cursor.remove() };
174 deferred_dealloc(removed);
175 removed
176 }
177}
178
179impl<T: Send + Sync + 'static, A: RcuListAdapter<T>> Drop for RcuList<T, A> {
180 fn drop(&mut self) {
181 unsafe { self.clear() };
183 }
184}
185
186#[cfg(test)]
187mod tests {
188 use crate::rcu_intrusive_list::{RcuListAdapter, rcu_list_adapter};
189
190 use super::*;
191 use fuchsia_rcu::rcu_synchronize;
192
193 #[derive(Debug)]
194 struct TestNode {
195 value: i64,
196 link: Link,
197 }
198
199 impl TestNode {
200 fn new(value: i64) -> Self {
201 Self { value, link: Default::default() }
202 }
203 }
204
205 impl RcuListAdapter<TestNode> for TestNode {
206 rcu_list_adapter!(TestNode, link);
207 }
208
209 #[test]
210 fn test_rcu_list_push_front() {
211 {
212 let list = RcuList::<TestNode, TestNode>::default();
213 let scope = RcuReadScope::new();
214 unsafe {
215 list.push_front(&scope, TestNode::new(1));
216 list.push_front(&scope, TestNode::new(2));
217 list.push_front(&scope, TestNode::new(3));
218 }
219
220 let mut cursor = list.cursor(&scope);
221 assert_eq!(cursor.current().map(|node| node.value), Some(3));
222 cursor.advance();
223 assert_eq!(cursor.current().map(|node| node.value), Some(2));
224 cursor.advance();
225 assert_eq!(cursor.current().map(|node| node.value), Some(1));
226 cursor.advance();
227 assert_eq!(cursor.current().map(|node| node.value), None);
228 }
229 rcu_synchronize();
230 }
231
232 #[test]
233 fn test_rcu_list_push_back() {
234 {
235 let list = RcuList::<TestNode, TestNode>::default();
236 let scope = RcuReadScope::new();
237 unsafe {
238 list.push_back(&scope, TestNode::new(1));
239 list.push_back(&scope, TestNode::new(2));
240 list.push_back(&scope, TestNode::new(3));
241 }
242
243 let mut cursor = list.cursor(&scope);
244 assert_eq!(cursor.current().map(|node| node.value), Some(1));
245 cursor.advance();
246 assert_eq!(cursor.current().map(|node| node.value), Some(2));
247 cursor.advance();
248 assert_eq!(cursor.current().map(|node| node.value), Some(3));
249 cursor.advance();
250 assert_eq!(cursor.current().map(|node| node.value), None);
251 }
252 rcu_synchronize();
253 }
254
255 #[test]
256 fn test_rcu_list_clear() {
257 {
258 let list = RcuList::<TestNode, TestNode>::default();
259 let scope = RcuReadScope::new();
260 unsafe {
261 list.push_back(&scope, TestNode::new(1));
262 list.push_back(&scope, TestNode::new(2));
263 list.push_back(&scope, TestNode::new(3));
264 }
265
266 unsafe { list.clear() };
267
268 let mut iter = list.iter(&scope);
269 assert_eq!(iter.next().map(|node| node.value), None);
270 }
271
272 rcu_synchronize();
273 }
274
275 #[test]
276 fn test_rcu_list_drop_clears_objects() {
277 use std::sync::Arc;
278 use std::sync::atomic::{AtomicUsize, Ordering};
279
280 #[derive(Debug)]
281 struct DropCounter {
282 _id: usize,
283 counter: Arc<AtomicUsize>,
284 link: Link,
285 }
286
287 impl RcuListAdapter<DropCounter> for DropCounter {
288 rcu_list_adapter!(DropCounter, link);
289 }
290
291 impl Drop for DropCounter {
292 fn drop(&mut self) {
293 self.counter.fetch_add(1, Ordering::SeqCst);
294 }
295 }
296
297 let drop_count = Arc::new(AtomicUsize::new(0));
298 {
299 let list = RcuList::<DropCounter, DropCounter>::default();
300 let scope = RcuReadScope::new();
301 unsafe {
302 list.push_back(
303 &scope,
304 DropCounter {
305 _id: 1,
306 counter: Arc::clone(&drop_count),
307 link: Default::default(),
308 },
309 );
310 list.push_back(
311 &scope,
312 DropCounter {
313 _id: 2,
314 counter: Arc::clone(&drop_count),
315 link: Default::default(),
316 },
317 );
318 list.push_back(
319 &scope,
320 DropCounter {
321 _id: 3,
322 counter: Arc::clone(&drop_count),
323 link: Default::default(),
324 },
325 );
326 }
327 assert_eq!(drop_count.load(Ordering::SeqCst), 0);
328 }
329
330 rcu_synchronize();
331
332 assert_eq!(drop_count.load(Ordering::SeqCst), 3);
334 }
335
336 #[test]
337 fn test_rcu_list_iter() {
338 {
339 let list = RcuList::<TestNode, TestNode>::default();
340 let scope = RcuReadScope::new();
341 unsafe {
342 list.push_back(&scope, TestNode::new(1));
343 list.push_back(&scope, TestNode::new(2));
344 list.push_back(&scope, TestNode::new(3));
345 }
346
347 let mut iter = list.iter(&scope);
348 assert_eq!(iter.next().map(|node| node.value), Some(1));
349 assert_eq!(iter.next().map(|node| node.value), Some(2));
350 assert_eq!(iter.next().map(|node| node.value), Some(3));
351 assert_eq!(iter.next().map(|node| node.value), None);
352 }
353
354 rcu_synchronize();
355 }
356
357 #[test]
358 fn test_rcu_list_remove() {
359 {
360 let list = RcuList::<TestNode, TestNode>::default();
361 let scope = RcuReadScope::new();
362 unsafe {
363 list.push_back(&scope, TestNode::new(1));
364 list.push_back(&scope, TestNode::new(2));
365 list.push_back(&scope, TestNode::new(3));
366 }
367
368 let mut cursor = list.cursor(&scope);
369 cursor.advance(); assert_eq!(cursor.current().map(|node| node.value), Some(2));
371 unsafe { cursor.remove() };
372
373 let mut iter = list.iter(&scope);
374 assert_eq!(iter.next().map(|node| node.value), Some(1));
375 assert_eq!(iter.next().map(|node| node.value), Some(3));
376 assert_eq!(iter.next().map(|node| node.value), None);
377
378 let mut cursor = list.cursor(&scope);
380 unsafe { cursor.remove() };
381
382 let mut iter = list.iter(&scope);
383 assert_eq!(iter.next().map(|node| node.value), Some(3));
384 assert_eq!(iter.next().map(|node| node.value), None);
385
386 let mut cursor = list.cursor(&scope);
388 unsafe { cursor.remove() };
389
390 let mut iter = list.iter(&scope);
391 assert_eq!(iter.next().map(|node| node.value), None);
392 }
393
394 rcu_synchronize();
395 }
396
397 #[test]
398 fn test_rcu_list_remove_all() {
399 {
400 let list = RcuList::<TestNode, TestNode>::default();
401 let scope = RcuReadScope::new();
402 unsafe {
403 list.push_back(&scope, TestNode::new(1));
404 list.push_back(&scope, TestNode::new(2));
405 list.push_back(&scope, TestNode::new(3));
406 }
407
408 let mut cursor = list.cursor(&scope);
409 while cursor.current().is_some() {
410 unsafe { cursor.remove() };
411 }
412
413 assert_eq!(list.iter(&scope).next().map(|node| node.value), None);
414 }
415
416 rcu_synchronize();
417 }
418
419 #[test]
420 fn test_rcu_list_append() {
421 {
422 let list1 = RcuList::<TestNode, TestNode>::default();
423 let scope = RcuReadScope::new();
424 unsafe {
425 list1.push_back(&scope, TestNode::new(1));
426 list1.push_back(&scope, TestNode::new(2));
427 }
428
429 let list2 = RcuList::<TestNode, TestNode>::default();
430 unsafe {
431 list2.push_back(&scope, TestNode::new(3));
432 list2.push_back(&scope, TestNode::new(4));
433 }
434
435 unsafe { list1.append(&scope, list2) };
436
437 let mut iter = list1.iter(&scope);
438 assert_eq!(iter.next().map(|node| node.value), Some(1));
439 assert_eq!(iter.next().map(|node| node.value), Some(2));
440 assert_eq!(iter.next().map(|node| node.value), Some(3));
441 assert_eq!(iter.next().map(|node| node.value), Some(4));
442 assert_eq!(iter.next().map(|node| node.value), None);
443 }
444
445 rcu_synchronize();
446 }
447
448 #[test]
449 fn test_rcu_list_append_empty() {
450 {
452 let list1 = RcuList::<TestNode, TestNode>::default();
453 let list2 = RcuList::<TestNode, TestNode>::default();
454 let scope = RcuReadScope::new();
455 unsafe {
456 list2.push_back(&scope, TestNode::new(1));
457 list2.push_back(&scope, TestNode::new(2));
458 }
459 unsafe { list1.append(&scope, list2) };
460
461 let mut iter = list1.iter(&scope);
462 assert_eq!(iter.next().map(|node| node.value), Some(1));
463 assert_eq!(iter.next().map(|node| node.value), Some(2));
464 assert_eq!(iter.next().map(|node| node.value), None);
465 }
466 rcu_synchronize();
467
468 {
470 let list1 = RcuList::<TestNode, TestNode>::default();
471 let scope = RcuReadScope::new();
472 unsafe {
473 list1.push_back(&scope, TestNode::new(1));
474 list1.push_back(&scope, TestNode::new(2));
475 }
476 let list2 = RcuList::<TestNode, TestNode>::default();
477 unsafe { list1.append(&scope, list2) };
478
479 let mut iter = list1.iter(&scope);
480 assert_eq!(iter.next().map(|node| node.value), Some(1));
481 assert_eq!(iter.next().map(|node| node.value), Some(2));
482 assert_eq!(iter.next().map(|node| node.value), None);
483 }
484 rcu_synchronize();
485 }
486
487 #[test]
488 fn test_rcu_list_is_empty() {
489 {
490 let list = RcuList::<TestNode, TestNode>::default();
491 let scope = RcuReadScope::new();
492 assert!(list.is_empty());
493
494 unsafe {
495 list.push_back(&scope, TestNode::new(1));
496 }
497 assert!(!list.is_empty());
498
499 unsafe {
500 list.clear();
501 }
502 assert!(list.is_empty());
503 }
504
505 rcu_synchronize();
506 }
507
508 #[test]
509 fn test_rcu_list_split_off() {
510 {
512 let list = RcuList::<TestNode, TestNode>::default();
513 let scope = RcuReadScope::new();
514 unsafe {
515 list.push_back(&scope, TestNode::new(1));
516 list.push_back(&scope, TestNode::new(2));
517 list.push_back(&scope, TestNode::new(3));
518 }
519
520 let new_list = unsafe { list.split_off(&scope, 0) };
521
522 assert!(list.is_empty());
523 let mut new_iter = new_list.iter(&scope);
524 assert_eq!(new_iter.next().map(|node| node.value), Some(1));
525 assert_eq!(new_iter.next().map(|node| node.value), Some(2));
526 assert_eq!(new_iter.next().map(|node| node.value), Some(3));
527 assert_eq!(new_iter.next().map(|node| node.value), None);
528 }
529 rcu_synchronize();
530
531 {
533 let list = RcuList::<TestNode, TestNode>::default();
534 let scope = RcuReadScope::new();
535 unsafe {
536 list.push_back(&scope, TestNode::new(1));
537 list.push_back(&scope, TestNode::new(2));
538 list.push_back(&scope, TestNode::new(3));
539 list.push_back(&scope, TestNode::new(4));
540 }
541
542 let new_list = unsafe { list.split_off(&scope, 2) };
543
544 let mut iter = list.iter(&scope);
545 assert_eq!(iter.next().map(|node| node.value), Some(1));
546 assert_eq!(iter.next().map(|node| node.value), Some(2));
547 assert_eq!(iter.next().map(|node| node.value), None);
548
549 let mut new_iter = new_list.iter(&scope);
550 assert_eq!(new_iter.next().map(|node| node.value), Some(3));
551 assert_eq!(new_iter.next().map(|node| node.value), Some(4));
552 assert_eq!(new_iter.next().map(|node| node.value), None);
553 }
554 rcu_synchronize();
555
556 {
558 let list = RcuList::<TestNode, TestNode>::default();
559 let scope = RcuReadScope::new();
560 unsafe {
561 list.push_back(&scope, TestNode::new(1));
562 list.push_back(&scope, TestNode::new(2));
563 list.push_back(&scope, TestNode::new(3));
564 }
565
566 let new_list = unsafe { list.split_off(&scope, 2) };
567
568 let mut iter = list.iter(&scope);
569 assert_eq!(iter.next().map(|node| node.value), Some(1));
570 assert_eq!(iter.next().map(|node| node.value), Some(2));
571 assert_eq!(iter.next().map(|node| node.value), None);
572
573 let mut new_iter = new_list.iter(&scope);
574 assert_eq!(new_iter.next().map(|node| node.value), Some(3));
575 assert_eq!(new_iter.next().map(|node| node.value), None);
576 }
577 rcu_synchronize();
578
579 {
581 let list = RcuList::<TestNode, TestNode>::default();
582 let scope = RcuReadScope::new();
583 unsafe {
584 list.push_back(&scope, TestNode::new(1));
585 list.push_back(&scope, TestNode::new(2));
586 list.push_back(&scope, TestNode::new(3));
587 }
588
589 let new_list = unsafe { list.split_off(&scope, 3) };
590
591 let mut iter = list.iter(&scope);
592 assert_eq!(iter.next().map(|node| node.value), Some(1));
593 assert_eq!(iter.next().map(|node| node.value), Some(2));
594 assert_eq!(iter.next().map(|node| node.value), Some(3));
595 assert_eq!(iter.next().map(|node| node.value), None);
596
597 assert!(new_list.is_empty());
598 }
599 rcu_synchronize();
600
601 {
603 let list = RcuList::<TestNode, TestNode>::default();
604 let scope = RcuReadScope::new();
605 unsafe {
606 list.push_back(&scope, TestNode::new(1));
607 list.push_back(&scope, TestNode::new(2));
608 list.push_back(&scope, TestNode::new(3));
609 }
610
611 let new_list = unsafe { list.split_off(&scope, 10) };
612
613 let mut iter = list.iter(&scope);
614 assert_eq!(iter.next().map(|node| node.value), Some(1));
615 assert_eq!(iter.next().map(|node| node.value), Some(2));
616 assert_eq!(iter.next().map(|node| node.value), Some(3));
617 assert_eq!(iter.next().map(|node| node.value), None);
618
619 assert!(new_list.is_empty());
620 }
621 rcu_synchronize();
622 }
623}