Struct crossbeam::Scope [] [src]

pub struct Scope<'a> { /* fields omitted */ }

Methods

impl<'a> Scope<'a>
[src]

Schedule code to be executed when exiting the scope.

This is akin to having a destructor on the stack, except that it is guaranteed to be run.

Create a scoped thread.

spawn is similar to the spawn function in Rust's standard library. The difference is that this thread is scoped, meaning that it's guaranteed to terminate before the current stack frame goes away, allowing you to reference the parent stack frame directly. This is ensured by having the parent thread join on the child thread before the scope exits.

Examples

A basic scoped thread:

crossbeam::scope(|scope| {
    scope.spawn(|| {
        println!("Hello from a scoped thread!");
    });
});

When writing concurrent Rust programs, you'll sometimes see a pattern like this, using std::thread::spawn:

let array = [1, 2, 3];
let mut guards = vec![];

for i in &array {
    let guard = std::thread::spawn(move || {
        println!("element: {}", i);
    });

    guards.push(guard);
}

for guard in guards {
    guard.join().unwrap();
}

The basic pattern is:

  1. Iterate over some collection.
  2. Spin up a thread to operate on each part of the collection.
  3. Join all the threads.

However, this code actually gives an error:

error: `array` does not live long enough
for i in &array {
          ^~~~~
in expansion of for loop expansion
note: expansion site
note: reference must be valid for the static lifetime...
note: ...but borrowed value is only valid for the block suffix following statement 0 at ...
    let array = [1, 2, 3];
    let mut guards = vec![];

    for i in &array {
        let guard = std::thread::spawn(move || {
            println!("element: {}", i);
...
error: aborting due to previous error

Because std::thread::spawn doesn't know about this scope, it requires a 'static lifetime. One way of giving it a proper lifetime is to use an Arc:

use std::sync::Arc;

let array = Arc::new([1, 2, 3]);
let mut guards = vec![];

for i in (0..array.len()) {
    let a = array.clone();

    let guard = std::thread::spawn(move || {
        println!("element: {}", a[i]);
    });

    guards.push(guard);
}

for guard in guards {
    guard.join().unwrap();
}

But this introduces unnecessary allocation, as Arc<T> puts its data on the heap, and we also end up dealing with reference counts. We know that we're joining the threads before our function returns, so just taking a reference should be safe. Rust can't know that, though.

Enter scoped threads. Here's our original example, using spawn from crossbeam rather than from std::thread:

let array = [1, 2, 3];

crossbeam::scope(|scope| {
    for i in &array {
        scope.spawn(move || {
            println!("element: {}", i);
        });
    }
});

Much more straightforward.

Trait Implementations

impl<'a> Debug for Scope<'a>
[src]

Formats the value using the given formatter.

impl<'a> Drop for Scope<'a>
[src]

A method called when the value goes out of scope. Read more