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,16 @@ 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 . list . compare_exchange ( list, Node :: EMPTY , SeqCst , SeqCst ) {
62
62
Ok ( _) => break ,
63
63
Err ( l) => list = l,
64
64
}
65
65
}
66
66
ArcList {
67
- list : AtomicUsize :: new ( list) ,
67
+ list : AtomicPtr :: new ( list) ,
68
68
_marker : marker:: PhantomData ,
69
69
}
70
70
}
@@ -73,7 +73,7 @@ impl<T> ArcList<T> {
73
73
/// `push`.
74
74
pub fn take_and_seal ( & self ) -> ArcList < T > {
75
75
ArcList {
76
- list : AtomicUsize :: new ( self . list . swap ( 1 , SeqCst ) ) ,
76
+ list : AtomicPtr :: new ( self . list . swap ( Node :: sealed ( ) , SeqCst ) ) ,
77
77
_marker : marker:: PhantomData ,
78
78
}
79
79
}
@@ -82,7 +82,7 @@ impl<T> ArcList<T> {
82
82
/// empty list.
83
83
pub fn pop ( & mut self ) -> Option < Arc < Node < T > > > {
84
84
let head = * self . list . get_mut ( ) ;
85
- if head == 0 || head == 1 {
85
+ if head == Node :: EMPTY || head == Node :: sealed ( ) {
86
86
return None ;
87
87
}
88
88
let head = unsafe { Arc :: from_raw ( head as * const Node < T > ) } ;
@@ -103,15 +103,21 @@ impl<T> Drop for ArcList<T> {
103
103
}
104
104
105
105
pub struct Node < T > {
106
- next : AtomicUsize ,
106
+ next : AtomicPtr < Node < T > > ,
107
107
enqueued : AtomicBool ,
108
108
data : T ,
109
109
}
110
110
111
111
impl < T > Node < T > {
112
+ const EMPTY : * mut Node < T > = std:: ptr:: null_mut ( ) ;
113
+
114
+ const fn sealed ( ) -> * mut Node < T > {
115
+ std:: ptr:: null_mut :: < Node < T > > ( ) . wrapping_add ( 1 )
116
+ }
117
+
112
118
pub fn new ( data : T ) -> Node < T > {
113
119
Node {
114
- next : AtomicUsize :: new ( 0 ) ,
120
+ next : AtomicPtr :: new ( Node :: EMPTY ) ,
115
121
enqueued : AtomicBool :: new ( false ) ,
116
122
data,
117
123
}
0 commit comments