Joining a thread in a method that takes `&mut self` (like drop) results in “cannot move out of borrowed content”

后端 未结 4 2018
梦如初夏
梦如初夏 2020-12-19 06:21

I want to create a thread inside of the new method and stop it after the struct is destroyed:

use std::thread;

struct Foo {
    handle: thread:         


        
4条回答
  •  隐瞒了意图╮
    2020-12-19 06:58

    The function signature of JoinHandle::join is:

    fn join(self) -> Result
    

    This means that the method takes self (the receiver object) by values (taking the ownership/consuming it). But you only have a borrow to your JoinHandle; a mutable one, but still merely a borrow, not the ownership. Thus you can't call this method, because you can't move the ownership out of your borrow into this join() method.

    An easy way to fix that, is by accepting self by value in the stop() method, too:

    pub fn stop(self) {
        self.handle.join();
    }
    

    But you will notice that this isn't possible when implementing Drop, because drop() has the signature fn drop(&mut self)! Bummer! But there is a little trick you can use, described below. Please be aware that joining threads in drop() is probably not a good idea! Read Matthieu M.'s answer for more information on that!

    If you still think, for whatever reason, that you really want to join a thread in drop(), you can store the JoinHandle in an Option to save whether or not it's already joined. If you have a Some(T) you can obtain a T (by value!) from it by using the method Option::take(). Then you can write:

    fn drop(&mut self) {
        // `self.handle` has the type `Option>` here!
        if let Some(handle) = self.handle.take() {
            handle.join().expect("failed to join thread");
        }
    }
    

提交回复
热议问题