[Solved] Lifetime for Arc + Mutex + Thread

#1

Hello Rustaceans,

I need to send a struct with a lifetime to a thread. I’d rather use some standard options instead of some crate solutions, if possible of course :slight_smile:

Here follows one example:

If I go this:

use std::marker::PhantomData;
use std::sync::{Arc, Mutex};
use std::thread;

struct SomeStruct<'a> {
    phantom: PhantomData<&'a ()>,
}

struct UpperStruct<'a> {
    somearc: Arc<Mutex<SomeStruct<'a>>>,
}

impl<'a> UpperStruct<'a> {
    fn another_method(&mut self) {
        let data = Arc::clone(&self.somearc);
        thread::spawn(move || {
            let mut data = data.lock().unwrap();
        });
    }
}

fn main() {}

I receive that:

error[E0477]: the type `[closure@src/main.rs:16:23: 18:10 data:std::sync::Arc<std::sync::Mutex<SomeStruct<'a>>>]` does not fulfill the required lifetime
  --> src/main.rs:16:9
   |
16 |         thread::spawn(move || {
   |         ^^^^^^^^^^^^^
   |
   = note: type must satisfy the static lifetime

Naturally, the Arc usage without lifetime works normally

use std::marker::PhantomData;
use std::sync::{Arc, Mutex};
use std::thread;

struct SomeStruct<'a> {
    phantom: PhantomData<&'a ()>,
}

struct UpperStruct<'a> {
    //somearc: Arc<Mutex<SomeStruct<'a>>>,
    somearc: Arc<Mutex<bool>>,
    phantom: PhantomData<&'a ()>,
}

impl<'a> UpperStruct<'a> {
    fn another_method(&mut self) {
        let data = Arc::clone(&self.somearc);
        thread::spawn(move || {
            let mut data = data.lock().unwrap();
        });
    }
}

fn main() {}
#2

Only crates provide the extra needed. Look at scopes in crossbeam or rayon

2 Likes
#3

thread::spawn forbids on purpose all structs tied to a temporary scope, so there is no amount of lifetime annotations or wrapper types that could change that.

@john’s suggestions are good. rayon::scope is probably what you need.

1 Like
#4

Ok, very good. I tested with rayon and it worked. Waiting anxiously for the stable version of async :smiley:

Anyway, here is the working code of this prototype to support some people who is having the same struggle

use rayon::prelude::*;

use std::marker::PhantomData;
use std::sync::{Arc, Mutex};

struct SomeStruct<'a> {
    phantom: PhantomData<&'a ()>,
}

struct UpperStruct<'a> {
    somearc: Arc<Mutex<SomeStruct<'a>>>,
    phantom: PhantomData<&'a ()>,
}

impl<'a> UpperStruct<'a> {
    fn another_method(&mut self) {
        let data = Arc::clone(&self.somearc);
        rayon::scope(|s| {
            s.spawn(move |_| {
                let mut data = data.lock().unwrap();
            });
        });
    }
}

fn main() {}

Thanks for the support, guys!