2015-08-26 9 views
5

Jestem nowy, aby zardzewieć i nadal mam problemy z własnością/pożyczaniem. W tym przypadku chcę zapisać FnOnce w wyliczeniu, a następnie wywołać go później z innego wątku. Próbowałem wielu różnych wariantów, ale zawsze utknąłem gdzieś. Tutaj jest zmniejszona wariant co obecnie mam:FnOnce inside Enum: nie można wyprowadzić z pożyczonej treści

#![feature(fnbox)] 

use std::sync::{Arc, Mutex}; 
use std::boxed::{Box, FnBox}; 

enum Foo<T> { 
    DoNothing, 
    CallFunction(Box<FnBox(&T) + Send>) 
} 

struct FooInMutex<T> { 
    foo: Arc<Mutex<Foo<T>>> 
} 

impl<T> FooInMutex<T> { 
    fn put_fn(&self, f: Box<FnBox(&T)+Send>) { 
     let mut foo = self.foo.lock().unwrap(); 
     let mut new_foo : Foo<T>; 
     match *foo { 
      Foo::DoNothing => 
       new_foo = Foo::CallFunction(f), 
      _ => 
       new_foo = Foo::DoNothing 
     } 
     *foo = new_foo; 
    } 

    fn do_it(&self, t: T) { 
     let mut foo = self.foo.lock().unwrap(); 
     let mut new_foo : Foo<T>; 
     match *foo { 
      Foo::CallFunction(ref mut f) => { 
       //f(&t) 
       f.call_box((&t,)); 
       new_foo = Foo::DoNothing; 
      } 
      _ => 
       panic!("...") 
     } 
     *foo = new_foo; 
    } 
} 

#[test] 
fn it_works() { 
    let x = FooInMutex { foo: Arch::new(Mutex::new(Foo::DoNothing)) }; 

    x.put_fn(Box::new(|| panic!("foo"))); 
    x.do_it(); 
} 

używam "rustc 1.4.0-nightly (e35fd7481 17.08.2015)". Komunikat o błędzie:

src/lib.rs:35:17: 35:18 error: cannot move out of borrowed content 
src/lib.rs:35     f.call_box((&t,)); 
          ^

Jak rozumiem, f jest własnością wyliczenia w mutex i ja tylko pożyczyć za pośrednictwem * foo. Ale do wywołania f, potrzebuję go przenieść. Ale jak to zrobić? Albo co jeszcze muszę zmienić, aby ten przykład zadziałał?

Odpowiedz

7

std::mem::replace jest co należy użyć tam coś takiego:

use std::mem; 

… 

    fn do_it(&self, t: T) { 
     match mem::replace(self.foo.lock().unwrap(), Foo::DoNothing) { 
      Foo::CallFunction(f) => { 
       f.call_box((&t,)); 
      } 
      _ => panic!("...") 
     } 
    } 
+0

odniesienia Dokumentacja: [std :: mem :: zastąpić] (http://doc.rust-lang.org/std/mem/ fn.replace.html) –

+0

Czy możesz wyjaśnić więcej dlaczego to się nie sprawdziło? Dlaczego 'f' musi zostać przeniesiony? – tafia

+0

@tafia: 'FnBox' jest oparty na' FnOnce', który pochłania środowisko zamknięcia; oznacza to, że 'f.call_box' przyjmuje' self' według wartości, więc 'f' musi być' Box '. Odmienne odniesienie do tego nie wystarczy, a zmienne odniesienie to wszystko, co masz w swoim początkowym przykładzie (stąd "nie można wyprowadzić z pożyczonego kontekstu", próbuje przenieść 'Box ' z zmienne odniesienie). –

Powiązane problemy