|
9 | 9 | //! information.
|
10 | 10 |
|
11 | 11 | use std::{
|
| 12 | + cell::RefCell, |
12 | 13 | sync::{
|
13 |
| - atomic::{AtomicPtr, AtomicU64, Ordering}, |
| 14 | + atomic::{AtomicU64, Ordering}, |
14 | 15 | Arc,
|
15 | 16 | },
|
16 | 17 | time::{Duration, Instant},
|
@@ -156,32 +157,24 @@ impl<T: TaskCell + Send + 'static> QueueCore<T> {
|
156 | 157 | }
|
157 | 158 | }
|
158 | 159 |
|
159 |
| -/// A holder to store task. We wrap the value in an atomic ptr because the return value of pop() |
160 |
| -/// only provide readonly reference to this value, though in our can it's safe to just take it. |
| 160 | +/// A holder to store task. Wrap the task in a RefCell becuase crossbeam-skip only provide |
| 161 | +/// readonly acess to a popped Entry. |
161 | 162 | struct Slot<T> {
|
162 |
| - ptr: AtomicPtr<T>, |
| 163 | + cell: RefCell<Option<T>>, |
163 | 164 | }
|
164 | 165 |
|
| 166 | +// It is safe here because the value is only visited by the thread which calls `pop()`. |
| 167 | +unsafe impl<T: Send> Sync for Slot<T> {} |
| 168 | + |
165 | 169 | impl<T> Slot<T> {
|
166 | 170 | fn new(value: T) -> Self {
|
167 | 171 | Self {
|
168 |
| - ptr: AtomicPtr::new(Box::into_raw(Box::new(value))), |
| 172 | + cell: RefCell::new(Some(value)), |
169 | 173 | }
|
170 | 174 | }
|
171 | 175 |
|
172 | 176 | fn take(&self) -> Option<T> {
|
173 |
| - let raw_ptr = self.ptr.swap(std::ptr::null_mut(), Ordering::SeqCst); |
174 |
| - if !raw_ptr.is_null() { |
175 |
| - unsafe { Some(*Box::from_raw(raw_ptr)) } |
176 |
| - } else { |
177 |
| - None |
178 |
| - } |
179 |
| - } |
180 |
| -} |
181 |
| - |
182 |
| -impl<T> Drop for Slot<T> { |
183 |
| - fn drop(&mut self) { |
184 |
| - self.take(); |
| 177 | + self.cell.take() |
185 | 178 | }
|
186 | 179 | }
|
187 | 180 |
|
@@ -350,7 +343,7 @@ impl Builder {
|
350 | 343 | .collect();
|
351 | 344 |
|
352 | 345 | let injector = TaskInjector {
|
353 |
| - queue: queue, |
| 346 | + queue, |
354 | 347 | task_manager: self.manager,
|
355 | 348 | };
|
356 | 349 |
|
|
0 commit comments