2016-12-08 2 views
0

これはより高いレベルの問題ですが、質問を解決するためにどの機能を使用する必要があるかわかりません。Rustのアプリケーションコンテキストのハンドルを作成する方法は?

ツール APIを持つグラフィカルアプリケーションを書くための最初のステップを取る、我々はアプリケーションのさまざまな部分を公開しcontext引数に渡したい場合があります:私は、これを書いたとき

// 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(); 
} 

ドキュメントが他のドキュメントのリストにも格納されているため、借用チェッカーの問題に遭遇しました。ドキュメントを一度に2つの場所で変更可能にしています。

私のプログラムをコンパイルするだけで、現在、リストからドキュメントを削除して、ツールを実行してから、ツールが終了したらドキュメントリストに戻します。

複数の引数を渡すことが可能な場合もありますが、上記の例は単純化されています。コンテキストのすべてのメンバーを引数として渡すことは実用的ではありません。

アプリケーションのコンテキストを、ツールコードに渡すことができるタイプにラップして、借用チェッカーで問題を起こすことはありませんか?

答えて

0

&は、データを関数に一時的に借用するために使用されます。通常、コード内の複数の場所からデータにアクセスする必要がある場合は、RcまたはArcタイプが必要です。

また、データに内部的な変更が必要な場合があります。この場合は、CellまたはRefCellにもラップする必要があります。

また、データがスレッド間で共有されている場合は、MutexまたはRwLockでラップする必要があります。

あなたのユースケースに応じて、すべてをデータ構造で合成する必要があります。詳細については読み:rust wrapper type composition

あなたの例では、次のようになります。

// 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(); 
} 

またはそれがマルチスレッド化されている場合:

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

は 'アーク<本当に必要な' RefCell'ですMutex >> '? 'Mutex :: unlock'によって返されたガードは、すでに基礎となるデータへの変更可能なアクセスを与えます。 – user4815162342

+0

あなたは正しいと思います。 RefCellはRcとの組み合わせでのみ必要です。 'Rc >' – eddy

関連する問題