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