6

I'm trying to retrieve the inner value of an Arc Mutex wrapper around an FLTK-RS Widget:

pub struct ArcWidget<T: Clone + WidgetExt + WidgetBase>(Arc<Mutex<T>>);


impl<T: Clone + WidgetExt + WidgetBase> ArcWidget<T>{    
    pub fn widg(&self)->T{
        let lock = self.0.clone();
        let lock2 = lock.into_inner().unwrap();
        lock2
    }
    pub fn redraw(&self){
        let mut widg = self.0.lock().unwrap();
        widg.redraw();
    }
}

However this results in error:

let lock = self.0.into_inner().unwrap().clone(); 
cannot move out of an `Arc` - move occurs because value has type `Mutex<T>`, which does not implement the `Copy` trait

I thought adding the Clone trait restriction would solve this, but apparently it did not. How might I address this error? WidgetExt+WidgetBase are incompatible with Copy, so I can not add a Copy trait restriction.

ANimator120
  • 2,556
  • 1
  • 20
  • 52
  • If you're returning `T` from `widg`, that means `widg` owns a `T` value. Given that, what are you expecting `self.0` to contain at that point? If that's the value you are trying to clone, so `widg` can own one and `self.0` owns one, then you need to stop using `into_inner`. – loganfsmyth Jun 18 '21 at 22:55
  • I guess I'm just confused about how I'm supposed to get T so I can feed it into other functions that require ```T: WidgetExt + WidgetBase```. I tried following the suggestion for [my previous question](https://stackoverflow.com/questions/68026220/debug-trait-not-satisfied-for-arc-mutex-when-trying-to-access-inner-value) and thought this was the right approach. Also, I thought this was a viable option given what I was seeing in the [answers to this similar question](https://stackoverflow.com/questions/29177449/how-to-take-ownership-of-t-from-arcmutext). – ANimator120 Jun 18 '21 at 23:02
  • I thought by using clone we were essentially just providing access to the inner ```T``` value, not removing the ```T``` value from inside of ```Arc>``` – ANimator120 Jun 18 '21 at 23:06
  • The `Arc::try_unwrap` in that answer is critical to it compiling, because that basically destroys the Arc to get at the inner value. Because you aren't doing that here, it is impossible to use `into_inner`. `try_unwrap` destroys the Arc to get at the inner Mutex, and `into_inner` destroys the mutex to get at the inner T. – loganfsmyth Jun 18 '21 at 23:14
  • The real question is, why do you want `widg` to return a `T`? Only one thing can own the `T` value at a time, so to do that, you'd either have to make a clone of it, or you'd have to destroy the Arc and the Mutex. It seems like really you want to lock the mutex and return something that allows you to access the widget. – loganfsmyth Jun 18 '21 at 23:19

1 Answers1

2

For pub fn widg(&self) -> T { to work, it would be necessary to make a full clone of the T value. W ith all the bounds in your question, that would look like this:

pub fn widg(&self) -> T {
    self.0.lock().unwrap().clone()
}

but that is very unlikely to be what you actually want. It seems like what you probably actually want is this:

pub fn widg(&self) -> &Mutex<T> {
    &self.0
}

because then code anywhere can do

let mut widg = self.widg().lock().unwrap();
widg.redraw();

or call any other method on the inner widget.

loganfsmyth
  • 156,129
  • 30
  • 331
  • 251
  • I see. For example, a function that I was planning on using the inner value for is [fltk::prelude::GroupExt::add_child(&mut self, &widg)](https://docs.rs/fltk/1.0.18/fltk/prelude/trait.GroupExt.html#tymethod.add) . ```widg``` needs to impliment ```WidgetExt```, and if we return a ```&Mutex```, then I get an error: ```WidgetExt is not implemented for MutexGuard<'_,T>```. ```pub fn widg(&self) -> T {self.0.lock().unwrap().clone()}``` did give me the results I was looking for! – ANimator120 Jun 18 '21 at 23:30
  • `self.widg().lock().unwrap();` returns `MutexGuard` that lets you access a `&WidgetExt`, the same way it can be used to call `widg.redraw();`. `fltk::prelude::GroupExt::add_child(&mut self, &widg)` would instead be `let widg = self.widg().lock().unwrap(); fltk::prelude::GroupExt::add_child(&mut self, &*widg);`. Note that it is `&*widg`, not `&widg` in the argument now. – loganfsmyth Jun 18 '21 at 23:39