# [−][src]Module crossbeam::deque

Concurrent work-stealing deques.

These data structures are most commonly used in work-stealing schedulers. The typical setup involves a number of threads, each having its own FIFO or LIFO queue (worker). There is also one global FIFO queue (injector) and a list of references to worker queues that are able to steal tasks (stealers).

We spawn a new task onto the scheduler by pushing it into the injector queue. Each worker thread waits in a loop until it finds the next task to run and then runs it. To find a task, it first looks into its local worker queue, and then into the injector and stealers.

# Queues

`Injector` is a FIFO queue, where tasks are pushed and stolen from opposite ends. It is shared among threads and is usually the entry point for new tasks.

`Worker` has two constructors:

- `new_fifo()` - Creates a FIFO queue, in which tasks are pushed and popped from opposite ends.
- `new_lifo()` - Creates a LIFO queue, in which tasks are pushed and popped from the same end.

Each `Worker` is owned by a single thread and supports only push and pop operations.

Method `stealer()` creates a `Stealer` that may be shared among threads and can only steal tasks from its `Worker`. Tasks are stolen from the end opposite to where they get pushed.

# Stealing

Steal operations come in three flavors:

1. `steal()` - Steals one task.
2. `steal_batch()` - Steals a batch of tasks and moves them into another worker.
3. `steal_batch_and_pop()` - Steals a batch of tasks, moves them into another queue, and pops one task from that worker.

In contrast to push and pop operations, stealing can spuriously fail with `Steal::Retry`, in which case the steal operation needs to be retried.

# Examples

Suppose a thread in a work-stealing scheduler is idle and looking for the next task to run. To find an available task, it might do the following:

1. Try popping one task from the local worker queue.
2. Try stealing a batch of tasks from the global injector queue.
3. Try stealing one task from another thread using the stealer list.

An implementation of this work-stealing strategy:

    use crossbeam_deque::{Injector, Steal, Stealer, Worker};
    use std::iter;

    fn find_task<T>(
        local: &Worker<T>,
        global: &Injector<T>,
        stealers: &[Stealer<T>],
    ) -> Option<T> {
        // Pop a task from the local queue, if not empty.
        local.pop().or_else(|| {
            // Otherwise, we need to look for a task elsewhere.
            iter::repeat_with(|| {
                // Try stealing a batch of tasks from the global queue.
                global.steal_batch_and_pop(local)
                    // Or try stealing a task from one of the other threads.
                    .or_else(|| stealers.iter().map(|s| s.steal()).collect())
            })
            // Loop while no task was stolen and any steal operation needs to be retried.
            .find(|s| !s.is_retry())
            // Extract the stolen task, if there is one.
            .and_then(|s| s.success())
        })
    }

## Structs

Injector | An injector queue.
Stealer | A stealer handle of a worker queue.
Worker | A worker queue.

## Enums

Steal | Possible outcomes of a steal operation.

# Help

## Keyboard Shortcuts

`?`
  Show this help dialog
`S`
  Focus the search field
`↑`
  Move up in search results
`↓`
  Move down in search results
`↹`
  Switch tab
`⏎`
  Go to active search result
`+`
  Expand all sections
`-`
  Collapse all sections

## Search Tricks

Prefix searches with a type followed by a colon (e.g., `fn:`) to restrict the search to a given type.

Accepted types are: `fn`, `mod`, `struct`, `enum`, `trait`, `type`, `macro`, and `const`.

Search functions by type signature (e.g., `vec -> usize` or `* -> vec`)

Search multiple things at once by splitting your query with comma (e.g., `str,u8` or `String,struct:Vec,test`)