多くのライブラリでは、指定された を実装する型を定義しtrait
て、コールバック ハンドラとして使用できます。これには、イベントを処理するために必要なすべてのデータを 1 つのデータ型にまとめる必要があり、借用が複雑になります。
たとえば、を実行mio
すると、構造体を実装Handler
して提供できます。これらの自明化されたデータ型の例を考えてみましょう:EventLoop
struct A {
pub b: Option<B>
};
struct B;
struct MyHandlerType {
pub map: BTreeMap<Token, A>,
pub pool: Pool<B>
}
ハンドラーには、Token
タイプ のアイテム から へのマップがありますA
。type の各アイテムには、 typeA
の関連付けられた値がある場合とない場合がありますB
。A
ハンドラーで、指定された の値を検索し、まだ値Token
がない場合B
は、ハンドラーの から値を取得しますPool<B>
。
impl Handler for MyHandlerType {
fn ready(&mut self, event_loop: &mut EventLoop<MyHandlerType>,
token: Token, events: EventSet) {
let a : &mut A = self.map.get_mut(token).unwrap();
let b : B = a.b.take().or_else(|| self.pool.new()).unwrap();
// Continue working with `a` and `b`
// ...
}
}
self.map
この配置では、とself.pool
が別個のエンティティであることを直感的に確認できますが、 にアクセスすると、 が ( を介して)self
既に借用されているとボロー チェッカーが文句を言います。self.map
self.pool
これに対する考えられるアプローチの 1 つは、各フィールドを でラップすることMyHandlerType
ですOption<>
。次に、メソッド呼び出しの開始時に、take()
これらの値を取り出しself
、呼び出しの最後に復元します。
struct MyHandlerType {
// Wrap these fields in `Option`
pub map: Option<BTreeMap<Token, A>>,
pub pool: Option<Pool<B>>
}
// ...
fn ready(&mut self, event_loop: &mut EventLoop<MyHandlerType>,
token: Token, events: EventSet) {
// Move these values out of `self`
let map = self.map.take().unwrap();
let pool = self.pool.take().unwrap();
let a : &mut A = self.map.get_mut(token).unwrap();
let b : B = a.b.take().or_else(|| self.pool.new()).unwrap();
// Continue working with `a` and `b`
// ...
// Restore these values to `self`
self.map = Some(map);
self.pool = Some(pool);
}
これは機能しますが、少しおかしな感じがします。self
また、メソッド呼び出しごとに値を出し入れするオーバーヘッドも発生します。
これを行う最善の方法は何ですか?