Sie versuchen, eine Closure aus mehreren Threads aufzurufen. Das heißt, teilen Sie die Schließung über mehrere Threads. Sobald der Ausdruck "über mehrere Threads teilen" in meinen Sinn kommt, ist mein erster Gedanke to reach for Arc
(mindestens bis RFC 458 ist in irgendeiner Form implementiert, wenn &
wird über Threads verwendbar werden). Dies ermöglicht sicheren Shared Memory (implementiert Clone
, ohne dass der interne Typ Clone
sein muss, da Clone
nur einen neuen Zeiger auf den gleichen Speicher erstellt), und so können Sie ein einzelnes Fn
Objekt verwenden, das in mehreren Threads verwendet wird, keine Notwendigkeit um es zu duplizieren.
Zusammenfassend, setzen Sie Ihre WithCall
in eine Arc
und klonen Sie das.
#![allow(unstable)]
use std::thread::Thread;
use std::sync::Arc;
type Fp = Box<Fn(i8,i8) -> i8 + Send + Sync>;
struct WithCall {
fp: Fp
}
impl WithCall {
pub fn new(fp: Fp) -> WithCall {
WithCall { fp: fp }
}
pub fn run(&self, a: i8, b: i8) -> i8 {
(*self.fp)(a, b)
}
}
fn main() {
let adder = WithCall::new(Box::new(|&: a: i8, b| a + b));
println!("{}", adder.run(1, 2));
let add_a = Arc::new(adder);
let add_b = add_a.clone();
Thread::scoped(move || {
println!("In remote thread: {}", add_a.run(10, 10));
});
Thread::scoped(move || {
println!("In remote thread: {}", add_b.run(10, 10));
});
}
playpen
Hinweis: Ich habe das unboxed_closures
Feature-Gate entfernt haben, indem die empfohlene Zucker Fn(...) -> ...
für Typen und direkte ()
Anrufe (nicht .call
verwenden). Außerdem habe ich die unnötige unsafe impl Send
entfernt, da Send
automatisch implementiert wird, wenn der Inhalt ist. unsafe impl
s sind nur erforderlich, wenn der Inhalt nicht standardmäßig Send
ist und der Programmierer die konservative Beurteilung des Compilers überschreiben möchte.
Alte Antwort (das ist immer noch relevant): Es ist ziemlich ungewöhnlich, dass ein &mut Fn
Merkmal Objekt zu haben, da Fn::call
&self
nimmt. Die mut
ist nicht notwendig, und ich denke, es fügt buchstäblich keine zusätzliche Funktionalität hinzu. Eine &mut Box<Fn()>
zu haben fügt einige Funktionalität hinzu, aber es ist auch ungewöhnlich.
Wenn Sie einen &
Zeiger anstelle eines &mut
Dinge ändern sich natürlich mehr arbeiten (beide mit &Fn
und &Box<Fn>
). Ohne den eigentlichen Code zu sehen, die Sie verwenden, ist es extrem schwer, genau zu sagen, was Sie tun, aber
fn call_it(f: &Fn()) {
(*f)();
(*f)();
}
fn use_closure(f: &Fn()) {
call_it(f);
call_it(f);
}
fn main() {
let x = 1i32;
use_closure(&|| println!("x is {}", x));
}
(Dies ist zum Teil auf &T
Copy
sein und auch zum Teil auf Beleihung, es funktioniert mit &mut
. auch)
Alternativ können Sie versenken sich über die Schließung, die wahrscheinlich in mehr Situationen funktioniert:
fn foo(f: &Fn()) {
something_else(|| f())
}
Obviously a FnMut cannot be cloned, for obvious reasons.
Es gibt keinen Grund, warum FnMut
nicht geklont werden kann. Es ist nur eine Struktur mit einigen Feldern (und eine Methode, die &mut self
statt &self
oder self
wie für Fn
bzw. FnOnce
nimmt). Wenn Sie eine Struktur erstellen und FnMut
manuell implementieren, können Sie dafür weiterhin Clone
implementieren.
Or is it safe to somehow pass a raw pointer to a Fn around, like:
let func_pnt = &mut Box<Fn<...> + Send> as *mut Box<Fn<...>>
Technically the above works, but it seems quite weird.
Technisch funktioniert es, wenn Sie vorsichtig sind sind die Aliasing und Anforderungen an die Lebensdauer von Rust, um sicherzustellen, zufrieden ... aber in unsichere Zeiger entscheiden werden Sie diese Last auf sich selbst setzen, nicht den Compiler helfen lassen Sie. Es ist relativ selten, dass die richtige Antwort auf einen Compiler-Fehler unsafe
Code ist, anstatt sich in den Fehler einzuarbeiten und den Code zu optimieren, um ihn sinnvoller zu machen (für den Compiler, was oft dazu führt, dass er für Menschen sinnvoller ist)).
Was würden Sie mit dem geklonten Schließung zu tun? – Shepmaster
Wie lautet Ihr vollständiger Code? – huon
@shepmaster Ich möchte speziell eine Schließung ohne veränderbaren Zustand klonen, um sie gleichzeitig in mehrere Aufgaben zu verschieben. Siehe das Beispiel, das ich angehängt habe. – Doug