Crate crossbeam_deque [−] [src]
A concurrent work-stealing deque.
The data structure can be thought of as a dynamically growable and shrinkable buffer that has
two ends: bottom and top. A Deque
can push
elements into the bottom and pop
elements from the bottom, but it can only steal
elements from the top.
A Deque
doesn't implement Sync
so it cannot be shared among multiple threads. However, it
can create Stealer
s, and those can be easily cloned, shared, and sent to other threads.
Stealer
s can only steal
elements from the top.
Here's a visualization of the data structure:
top
_
Deque::steal -> | | <- Stealer::steal
| |
| |
| |
Deque::push/pop -> |_|
bottom
Work-stealing schedulers
Usually, the data structure is used in work-stealing schedulers as follows.
There is a number of threads. Each thread owns a Deque
and creates a Stealer
that is
shared among all other threads. Alternatively, it creates multiple Stealer
s - one for each
of the other threads.
Then, all threads are executing in a loop. In the loop, each one attempts to pop
some work
from its own Deque
. But if it is empty, it attempts to steal
work from
some other thread instead. When executing work (or being idle), a thread may produce more work,
which gets push
ed into its Deque
.
Of course, there are many variations of this strategy. For example, sometimes it may be
beneficial for a thread to always steal
work from the top of its deque
instead of calling pop
and taking it from the bottom.
Examples
use crossbeam_deque::{Deque, Steal}; use std::thread; let d = Deque::new(); let s = d.stealer(); d.push('a'); d.push('b'); d.push('c'); assert_eq!(d.pop(), Some('c')); drop(d); thread::spawn(move || { assert_eq!(s.steal(), Steal::Data('a')); assert_eq!(s.steal(), Steal::Data('b')); }).join().unwrap();
References
The implementation is based on the following work:
Structs
Deque |
A concurrent work-stealing deque. |
Stealer |
A stealer that steals elements from the top of a deque. |
Enums
Steal |
Possible outcomes of a steal operation. |