3 Stimmen

Wie kann man bewirken, dass die Methode für das gesperrte Mutex kein veränderliches self erfordert?

Das Lesen eines Feldes einer Struktur in einem Rost Spielplatz:

use std::sync::Mutex;
#[deriving(Show)]
struct Test{
    a: uint,
}
impl Test{
    fn new() -> Test{
        Test { a: 0}
    }
    fn get(&self) -> uint {
        self.a
    }
}
fn main() {
    let t = Test{a: 42};
    let m = Mutex::new(Test::new());
    println!("t abrufen: {} wobei t.a = {}", t.get(), t.a);
    {
        let m2 = m.lock();
        println!("m2.a = {}", m2.a); // funktioniert
        //println!("m2.get() = {}", m2.get()); // Fehler: Kann lokale unveränderliche Variable `m2` nicht als veränderlich ausleihen
    }
}

Also in diesem Fall funktioniert der Zugriff auf das Feld m2.a, aber das Aufrufen von m2.get() erfordert, dass m2 veränderlich ist, obwohl get nichts verändert und nicht deklariert ist, etwas zu verändern, insbesondere nicht &self.

Um diesen Code zum Laufen zu bringen, könnte ich einfach let mut m2 = m.lock(); deklarieren und alles funktioniert gut, aber warum brauche ich dieses mut hier und gibt es einen besseren Weg, um m2.get() aufzurufen, ohne m2 als veränderlich zu deklarieren, ähnlich wie es für t funktioniert, den ich als nicht veränderlich deklariere und der mir trotzdem erlaubt, t.get() aufzurufen.

4voto

sellibitze Punkte 26706

Ja, der Compiler tendiert dazu, deref_mut gegenüber deref anzurufen, falls beide verfügbar sind. In Ihrem Fall würde deref ausreichen und funktionieren, aber die implizite Dereferenzierungsmaschinerie wählt stattdessen deref_mut aus und beschwert sich dann darüber, dass m2 nicht veränderbar ist.

Um das, was reem gesagt hat, hinzuzufügen, implementiert das Sperrobjekt sowohl Deref als auch DerefMut und wenn Sie keinen veränderbaren Verweis benötigen, können Sie den unveränderlichen durch explizites Reborren erhalten:

println!("m2.get() = {}", (&*m2).get());

Und wenn dieser Art von Zugriff alles ist, was Sie benötigen, können Sie auch schreiben

let m2 = m.lock();
let m2 = &*m2;

was dann ermöglicht

println!("m2.get() = {}", m2.get());

3voto

reem Punkte 7186

Dies ist auf eine leichte Einschränkung der Deref-Traits-Familie zurückzuführen - nämlich ist die Implementierung sowohl von Deref als auch von DerefMut für denselben Typ derzeit etwas fehlerhaft aufgrund des Verhaltens von Autoderef für Methoden, nämlich wird immer deref_mut aufgerufen, selbst um & Referenzen zu erhalten.

Als Ergebnis muss MutexGuard veränderbar sein, um Methoden aufrufen zu können, die &self benötigen. Normalerweise sind unveränderliche Verwendungen von Mutex selten, und RWLock, das sowohl Lese- als auch Schreibsperren separat unterstützt, ist für diesen Anwendungsfall besser geeignet, da es gleichzeitige Lesezugriffssperren ermöglicht.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X