2016-12-08 2 views
0

Dies ist ein höheres Problem, aber ich bin mir nicht sicher, welche Funktionen von Rust verwendet werden sollten, um die Frage zu verfeinern.Wie erstellt man ein Handle für den Anwendungskontext in Rust?

die ersten Schritte eine grafische Anwendung zu schreiben, die einen Werkzeug API hat, könnten wir den Ball in einem context Argumente wollen, die verschiedenen Teile der Anwendung macht:

// Where the data lives. 
struct Application { 
    preferences: Preferences, 
    windows: Vec<Windows>, 
    documents: Vec<Document>, 
} 

// A view on the data to pass to tool-code. 
struct AppContext { 
    preferences: &Preferences, // immutable 
    window: &Window,   // immutable 
    doc: &Document,    // mutable 
    // ... real world use case has more vars ... 
} 

// example use 
fn some_tool_uppercase(context: &mut AppContext, options: &ToolOptions) { 
    // random example 
    for w in context.document.words { 
     w.to_uppercase(); 
    } 
    context.window.redraw_tag(); 
} 

Wenn dieses Schreiben, ich Probleme mit dem Border-Checker, da das Dokument auch in einer Liste anderer Dokumente gespeichert ist - wodurch es an zwei Stellen gleichzeitig änderbar ist.

Nur um mein Programm kompilieren zu lassen, entferne ich derzeit das Dokument aus der Liste, führe das Werkzeug aus und füge es dann wieder in die Dokumentenliste ein, wenn das Werkzeug fertig ist.

Während es in einigen Fällen möglich ist, mehrere Argumente zu übergeben, ist das obige Beispiel vereinfacht. Es ist unpraktisch, jedes Mitglied des Kontexts als Argument zu übergeben.

Wie soll der Kontext einer Anwendung in einen Typ eingebettet werden, der in den Werkzeugcode übernommen werden kann, ohne dass es zu Komplikationen beim Border Checker kommt?

Antwort

0

Die & dient zum vorübergehenden Ausleihen von Daten an eine Funktion. Wenn Sie Zugriff auf Daten von mehreren Stellen im Code haben müssen, benötigen Sie normalerweise den Typ Rc oder Arc.

Zusätzlich möchten Sie möglicherweise interne Veränderlichkeit für Ihre Daten. In diesem Fall müssen Sie es auch in Cell oder RefCell wickeln.

Und wenn Ihre Daten zwischen Threads geteilt werden, müssen Sie es auch um eine Mutex oder RwLock wickeln.

Jetzt abhängig von Ihrem Anwendungsfall müssen Sie all dies in Ihrer Datenstruktur zusammensetzen. Für weitere Informationen lesen: rust wrapper type composition

Ihr Beispiel könnte wie folgt aussehen:

// Where the data lives. 
struct Application { 
    preferences: Rc<Preferences>, 
    windows: Rc<Vec<Windows>>, 
    document: Rc<RefCell<Vec<Document>>>, 
} 

// A view on the data to pass to tool-code. 
struct AppContext { 
    preferences: Rc<Preferences>, // immutable 
    window: Rc<Window>,   // immutable 
    document: Rc<RefCell<Document>>,    // mutable 
    // ... real world use case has more vars ... 
} 

// example use 
fn some_tool_uppercase(context: &mut AppContext, options: &ToolOptions) { 
    // random example 
    for w in (*context.document.borrow_mut()).words { 
     w.to_uppercase(); 
    } 
    context.window.redraw_tag(); 
} 

oder wenn es multi-threaded:

struct Application { 
    preferences: Arc<RwLock<Preferences>>, 
    windows: Arc<Mutex<Vec<Windows>>>, 
    document: Arc<Mutex<Vec<Document>>, 
} 
.... 
+0

Ist das 'RefCell' wirklich notwendig in' Arc < Mutex >> '? Der von 'Mutex :: unlock' zurückgegebene Guard gibt bereits einen veränderbaren Zugriff auf die zugrundeliegenden Daten. – user4815162342

+0

Ich denke, du hast Recht. RefCell wird nur in Kombination mit Rc benötigt. 'Rc >' – eddy

Verwandte Themen