1
- // Copyright 2017 the authors. See the 'Copyright and license' section of the
1
+ // Copyright 2017-2018 the authors. See the 'Copyright and license' section of the
2
2
// README.md file at the top-level directory of this repository.
3
3
//
4
4
// Licensed under the Apache License, Version 2.0 (the LICENSE-APACHE file) or
8
8
//! Specification of best-effort bags and implementation for `crossbeam`
9
9
//! data-structures.
10
10
use super :: crossbeam:: sync:: { TreiberStack , SegQueue , MsQueue } ;
11
- use super :: crossbeam :: mem :: epoch ;
11
+ use super :: crossbeam_epoch :: { Collector , Guard , Handle } ;
12
12
use std:: sync:: atomic:: AtomicUsize ;
13
13
use std:: sync:: Arc ;
14
14
@@ -22,52 +22,47 @@ pub enum PopStatus {
22
22
23
23
pub type PopResult < T > = Result < T , PopStatus > ;
24
24
25
-
26
25
/// A best-effort Bag data-structure.
27
26
///
28
27
/// As embodied in the `PopResult` definition, `try_pop` is permitted to
29
28
/// fail even if the bag in question is not empty.
30
- pub trait SharedWeakBag {
29
+ pub trait SharedWeakBag where Self : Sized {
31
30
type Item ;
31
+
32
32
/// Returns a new instance of the data-structure.
33
33
fn new ( ) -> Self ;
34
34
35
35
/// Attempts to push `it` onto the data-structure.
36
36
///
37
37
/// If successful, `try_push` will return `true`.
38
- fn try_push ( & self , it : Self :: Item ) -> Result < ( ) , Self :: Item > ;
38
+ fn try_push ( & self , guard : & Guard , it : Self :: Item ) -> Result < ( ) , Self :: Item > ;
39
39
40
40
/// Attempts to pop a value from the data-structure.
41
41
///
42
42
/// There is no guaranteed ordering of popped values. This method
43
43
/// may fail arbitrarily even if there are accessible values in the
44
44
/// data-structure.
45
- fn try_pop ( & self ) -> PopResult < Self :: Item > ;
45
+ fn try_pop ( & self , guard : & Guard ) -> PopResult < Self :: Item > ;
46
46
47
47
/// A push operation that will not fail.
48
48
///
49
49
/// The default implementation of `push` simply calls `try_push`
50
50
/// in a loop. until it succeeds. Depending on the underlying
51
51
/// data-structure this may loop infinitely under some
52
52
/// circumstances.
53
- ///
54
- /// `push` also creates a `Guard` for the duration of the function
55
- /// to avoid excessive checking in the hot loop.
56
- fn push ( & self , it : Self :: Item ) {
57
- let _g = epoch:: pin ( ) ;
53
+ fn push ( & self , guard : & Guard , it : Self :: Item ) {
58
54
let mut cur_item = it;
59
- while let Err ( old_item) = self . try_push ( cur_item) {
55
+ while let Err ( old_item) = self . try_push ( guard , cur_item) {
60
56
cur_item = old_item
61
57
}
62
58
}
63
59
64
60
/// A pop operation that will not fail.
65
61
///
66
62
/// Same caveats apply to those of `push`.
67
- fn pop ( & self ) -> Option < Self :: Item > {
68
- let _g = epoch:: pin ( ) ;
63
+ fn pop ( & self , guard : & Guard ) -> Option < Self :: Item > {
69
64
loop {
70
- return match self . try_pop ( ) {
65
+ return match self . try_pop ( guard ) {
71
66
Ok ( it) => Some ( it) ,
72
67
Err ( PopStatus :: Empty ) => None ,
73
68
Err ( PopStatus :: TransientFailure ) => continue ,
@@ -88,24 +83,24 @@ pub trait SharedWeakBag {
88
83
pub trait WeakBag : Clone {
89
84
// TODO(ezrosent): should we keep Clone here?
90
85
type Item ;
91
- // fn new() -> Self;
86
+
92
87
fn try_push_mut ( & mut self , Self :: Item ) -> Result < ( ) , Self :: Item > ;
93
88
fn try_pop_mut ( & mut self ) -> PopResult < Self :: Item > ;
94
89
fn push_mut ( & mut self , it : Self :: Item ) {
95
- let _g = epoch :: pin ( ) ;
90
+ // TODO(joshlf): Pin the WeakBag's GC for performance
96
91
let mut cur_item = it;
97
92
while let Err ( old_item) = self . try_push_mut ( cur_item) {
98
93
cur_item = old_item
99
94
}
100
95
}
101
96
fn pop_mut ( & mut self ) -> Option < Self :: Item > {
102
- let _g = epoch :: pin ( ) ;
97
+ // TODO(joshlf): Pin the WeakBag's GC for performance
103
98
loop {
104
- return match self . try_pop_mut ( ) {
105
- Ok ( it) => Some ( it) ,
106
- Err ( PopStatus :: Empty ) => None ,
107
- Err ( PopStatus :: TransientFailure ) => continue ,
108
- } ;
99
+ match self . try_pop_mut ( ) {
100
+ Ok ( it) => break Some ( it) ,
101
+ Err ( PopStatus :: Empty ) => break None ,
102
+ Err ( PopStatus :: TransientFailure ) => { }
103
+ }
109
104
}
110
105
}
111
106
@@ -120,25 +115,46 @@ pub trait WeakBag: Clone {
120
115
}
121
116
}
122
117
123
- pub struct ArcLike < B > ( Arc < B > ) ;
118
+ pub struct ArcLike < B > {
119
+ arc : Arc < B > ,
120
+ gc : Handle ,
121
+ }
124
122
125
123
impl < B > Clone for ArcLike < B > {
126
124
fn clone ( & self ) -> Self {
127
- ArcLike ( self . 0 . clone ( ) )
125
+ ArcLike {
126
+ arc : self . arc . clone ( ) ,
127
+ gc : self . gc . clone ( ) ,
128
+ }
128
129
}
129
130
}
130
131
131
132
impl < B : SharedWeakBag > Default for ArcLike < B > {
132
- fn default ( ) -> Self { ArcLike ( Arc :: new ( B :: new ( ) ) ) }
133
+ fn default ( ) -> Self {
134
+ ArcLike {
135
+ arc : Arc :: new ( B :: new ( ) ) ,
136
+ gc : Collector :: new ( ) . handle ( ) ,
137
+ }
138
+ }
133
139
}
134
140
135
141
impl < B : SharedWeakBag > WeakBag for ArcLike < B > {
136
142
type Item = B :: Item ;
143
+
137
144
fn try_push_mut ( & mut self , it : Self :: Item ) -> Result < ( ) , Self :: Item > {
138
- self . 0 . try_push ( it)
145
+ self . arc . try_push ( & self . gc . pin ( ) , it)
139
146
}
147
+
140
148
fn try_pop_mut ( & mut self ) -> PopResult < Self :: Item > {
141
- self . 0 . try_pop ( )
149
+ self . arc . try_pop ( & self . gc . pin ( ) )
150
+ }
151
+
152
+ fn push_mut ( & mut self , it : Self :: Item ) {
153
+ self . arc . push ( & self . gc . pin ( ) , it)
154
+ }
155
+
156
+ fn pop_mut ( & mut self ) -> Option < Self :: Item > {
157
+ self . arc . pop ( & self . gc . pin ( ) )
142
158
}
143
159
}
144
160
@@ -197,14 +213,17 @@ where
197
213
198
214
impl < T > SharedWeakBag for TreiberStack < T > {
199
215
type Item = T ;
216
+
200
217
fn new ( ) -> Self {
201
218
Self :: new ( )
202
219
}
203
- fn try_push ( & self , t : T ) -> Result < ( ) , T > {
220
+
221
+ fn try_push ( & self , _guard : & Guard , t : T ) -> Result < ( ) , T > {
204
222
self . push ( t) ;
205
223
Ok ( ( ) )
206
224
}
207
- fn try_pop ( & self ) -> PopResult < T > {
225
+
226
+ fn try_pop ( & self , _guard : & Guard ) -> PopResult < T > {
208
227
match self . pop ( ) {
209
228
Some ( res) => Ok ( res) ,
210
229
None => Err ( PopStatus :: Empty ) ,
@@ -214,14 +233,17 @@ impl<T> SharedWeakBag for TreiberStack<T> {
214
233
215
234
impl < T > SharedWeakBag for SegQueue < T > {
216
235
type Item = T ;
236
+
217
237
fn new ( ) -> Self {
218
238
Self :: new ( )
219
239
}
220
- fn try_push ( & self , t : T ) -> Result < ( ) , T > {
240
+
241
+ fn try_push ( & self , _guard : & Guard , t : T ) -> Result < ( ) , T > {
221
242
self . push ( t) ;
222
243
Ok ( ( ) )
223
244
}
224
- fn try_pop ( & self ) -> PopResult < T > {
245
+
246
+ fn try_pop ( & self , _guard : & Guard ) -> PopResult < T > {
225
247
match self . try_pop ( ) {
226
248
Some ( res) => Ok ( res) ,
227
249
None => Err ( PopStatus :: Empty ) ,
@@ -231,14 +253,17 @@ impl<T> SharedWeakBag for SegQueue<T> {
231
253
232
254
impl < T > SharedWeakBag for MsQueue < T > {
233
255
type Item = T ;
256
+
234
257
fn new ( ) -> Self {
235
258
Self :: new ( )
236
259
}
237
- fn try_push ( & self , t : T ) -> Result < ( ) , T > {
260
+
261
+ fn try_push ( & self , _guard : & Guard , t : T ) -> Result < ( ) , T > {
238
262
self . push ( t) ;
239
263
Ok ( ( ) )
240
264
}
241
- fn try_pop ( & self ) -> PopResult < T > {
265
+
266
+ fn try_pop ( & self , _guard : & Guard ) -> PopResult < T > {
242
267
match self . try_pop ( ) {
243
268
Some ( res) => Ok ( res) ,
244
269
None => Err ( PopStatus :: Empty ) ,
0 commit comments