3
3
use std:: marker;
4
4
use std:: ops:: Deref ;
5
5
use std:: sync:: atomic:: Ordering :: SeqCst ;
6
- use std:: sync:: atomic:: { AtomicBool , AtomicUsize } ;
6
+ use std:: sync:: atomic:: { AtomicBool , AtomicPtr } ;
7
7
use std:: sync:: Arc ;
8
8
9
9
pub struct ArcList < T > {
10
- list : AtomicUsize ,
10
+ list : AtomicPtr < Node < T > > ,
11
11
_marker : marker:: PhantomData < T > ,
12
12
}
13
13
14
14
impl < T > ArcList < T > {
15
15
pub fn new ( ) -> ArcList < T > {
16
16
ArcList {
17
- list : AtomicUsize :: new ( 0 ) ,
17
+ list : AtomicPtr :: new ( Node :: EMPTY ) ,
18
18
_marker : marker:: PhantomData ,
19
19
}
20
20
}
@@ -31,10 +31,10 @@ impl<T> ArcList<T> {
31
31
return Ok ( ( ) ) ;
32
32
}
33
33
let mut head = self . list . load ( SeqCst ) ;
34
- let node = Arc :: into_raw ( data. clone ( ) ) as usize ;
34
+ let node = Arc :: into_raw ( data. clone ( ) ) as * mut Node < T > ;
35
35
loop {
36
36
// If we've been sealed off, abort and return an error
37
- if head == 1 {
37
+ if head == Node :: SEALED {
38
38
unsafe {
39
39
drop ( Arc :: from_raw ( node as * mut Node < T > ) ) ;
40
40
}
@@ -55,16 +55,19 @@ impl<T> ArcList<T> {
55
55
pub fn take ( & self ) -> ArcList < T > {
56
56
let mut list = self . list . load ( SeqCst ) ;
57
57
loop {
58
- if list == 1 {
58
+ if list == Node :: SEALED {
59
59
break ;
60
60
}
61
- match self . list . compare_exchange ( list, 0 , SeqCst , SeqCst ) {
61
+ match self
62
+ . list
63
+ . compare_exchange ( list, Node :: EMPTY , SeqCst , SeqCst )
64
+ {
62
65
Ok ( _) => break ,
63
66
Err ( l) => list = l,
64
67
}
65
68
}
66
69
ArcList {
67
- list : AtomicUsize :: new ( list) ,
70
+ list : AtomicPtr :: new ( list) ,
68
71
_marker : marker:: PhantomData ,
69
72
}
70
73
}
@@ -73,7 +76,7 @@ impl<T> ArcList<T> {
73
76
/// `push`.
74
77
pub fn take_and_seal ( & self ) -> ArcList < T > {
75
78
ArcList {
76
- list : AtomicUsize :: new ( self . list . swap ( 1 , SeqCst ) ) ,
79
+ list : AtomicPtr :: new ( self . list . swap ( Node :: SEALED , SeqCst ) ) ,
77
80
_marker : marker:: PhantomData ,
78
81
}
79
82
}
@@ -82,7 +85,7 @@ impl<T> ArcList<T> {
82
85
/// empty list.
83
86
pub fn pop ( & mut self ) -> Option < Arc < Node < T > > > {
84
87
let head = * self . list . get_mut ( ) ;
85
- if head == 0 || head == 1 {
88
+ if head == Node :: EMPTY || head == Node :: SEALED {
86
89
return None ;
87
90
}
88
91
let head = unsafe { Arc :: from_raw ( head as * const Node < T > ) } ;
@@ -103,15 +106,19 @@ impl<T> Drop for ArcList<T> {
103
106
}
104
107
105
108
pub struct Node < T > {
106
- next : AtomicUsize ,
109
+ next : AtomicPtr < Node < T > > ,
107
110
enqueued : AtomicBool ,
108
111
data : T ,
109
112
}
110
113
111
114
impl < T > Node < T > {
115
+ const EMPTY : * mut Node < T > = std:: ptr:: null_mut ( ) ;
116
+
117
+ const SEALED : * mut Node < T > = std:: ptr:: null_mut :: < Node < T > > ( ) . wrapping_add ( 1 ) ;
118
+
112
119
pub fn new ( data : T ) -> Node < T > {
113
120
Node {
114
- next : AtomicUsize :: new ( 0 ) ,
121
+ next : AtomicPtr :: new ( Node :: EMPTY ) ,
115
122
enqueued : AtomicBool :: new ( false ) ,
116
123
data,
117
124
}
0 commit comments