2

I have a program that has an object oriented struct which has functions in it that use threading (std::thread). In the threads I want to access "self". Unfortunately when I do that, I get this unhelpful error:

error[E0521]: borrowed data escapes outside of associated function
   --> src\screens\map\map.rs:170:34
    |
67  |           &mut self,
    |           ---------
    |           |
    |           `self` is a reference that is only valid in the associated function body
    |           let's call the lifetime of this reference `'1`
...
170 |                       let handle = thread::spawn(move || {
    |  __________________________________^
171 | |                         let renderbytes = self.cloudslayer.render(
172 | |                             runtimechunksize as u32,
173 | |                             runtimechunksize as u32,
...   |
179 | |                         renderbytes
180 | |                     });
    | |                      ^
    | |                      |
    | |______________________`self` escapes the associated function body here
    |                        argument requires that `'1` must outlive `'static`

error[E0382]: borrow of moved value: `self`
   --> src\screens\map\map.rs:340:9
    |
67  |           &mut self,
    |           --------- move occurs because `self` has type `&mut screens::map::map::Map`, which does not implement the `Copy` trait
...
170 |                       let handle = thread::spawn(move || {
    |                                                  ------- value moved into closure here, in previous iteration of loop
...
340 | /         self.cachedrenderedchunks
341 | |             .retain(|key, _| chunksonscreen.contains(key))
    | |__________________________________________________________^ value borrowed here after move

Here is the thread:

let handle = thread::spawn(move || {
    let renderbytes = self.cloudslayer.render(
        runtimechunksize as u32,
        runtimechunksize as u32,
        x,
        y,
        lod,
    );

    renderbytes
});

I have only been programming in rust for about 3 weeks now, and so I am sure there is some dumb reason why this doesn't work, but any help would be greatly appreciated.

James Gaunt
  • 119
  • 1
  • 14
  • It is complaining, because this would potentially violate the mutability rules and cause undefined behavior. A thread, can not determine the lifetime of types on other threads. Because of this, `move` is used to give the closure ownership of the data it uses. Since `self` is access via a mutable reference you do not have the ownership of `self` required to move it into the thread. The only way for the lifetime of the mutable reference to be sufficient would be if it lived for `'static` or in other words, if it was an owned value. – Locke Aug 28 '22 at 00:41
  • You have 2 options to fix this. Either you can give `self` to the new thread or you wrap it in a synchronization structure that can safely share the data between the 2 threads. To give self to the thread, all you need to due is change `&mut self` in the function signature to `mut self` so the function will consume `self` when called. As for the synchronization structures, you can wrap your type in a thread safe structure like a `Arc>` which will prevent 2 threads from reading/writing to the data at the same time. – Locke Aug 28 '22 at 00:45
  • Thanks, I can see why my idea of transferring self between threads is an inefficient approach to my problem. I have refactored my code to avoid this functionality. Thanks for the help. – James Gaunt Aug 28 '22 at 02:22

0 Answers0