Future を実装するには Item, Error と poll 関数があればよい
impl Future for Something {
type Item = ();
type Error = Never;
fn poll(&mut self, _cx: &mut Context) -> Poll<Self::Item, Self::Error> {
//
}
}
LocalPool は 同じスレッド内で非同期処理するためのもの (task とも呼ばれる)
let mut pool = LocalPool::new();
LocalExecutor は Pool 単位でタスク実行時に内部で呼ばれるもの
let mut exec = pool.executor();
lazy で遅延処理用の関数(FnOnce)をFutureとしてラップし、
let f = lazy(move |_| -> FutureResult<Something, Never> {
//
});
それを pool の run_until 関数に に executer と一緒に呼び出すと非同期処理をはじめさせることができる
let res = pool.run_until(f, &mut exec)
run_until は複数定義できたりもしますので、DB処理などをバックグラウンドで処理させることなどにも利用できます。
exec.spawn_local は spawn のスレッド内版 (Sendを実装されていない)
exec.spawn_local(lazy(move |_| {
Ok(())
})).unwrap();
Poolから複数のexecutorを生成して、spawn_local内にspawn_localすることもできる。(nested)
spawn まわりは、所有権は渡さないといけないので move する必要がある。
let mut exec = pool.executor();
let mut exec_2 = pool.executor();
let _ = exec.spawn_local(lazy(move |_| {
exec_2.spawn_local(lazy(move |_| {
//
Ok(())
})).unwrap();
Ok(())
}));
あと,中で共通のデータを触りたい場合は、Rc (Reference Count)でラップするとよい、同じスレッドなので、Arc (Atomic Rc)は必要ない。
let cnt = Rc::new(Cell::new(something));
let cnt_2 = cnt.clone();
LocalPool を使わずに ThreadPool を使って Channel でやり取りする方法もある。
仮に pool 2つ使うとして、ThreadPoolをこんな感じで作れます。
let mut cpu_pool = ThreadPoolBuilder::new()
.pool_size(2)
.create().unwrap();
送信者2つ用のChannelを作り
let (tx, rx) = mpsc::sync_channel(2);
let tx_2 = tx.clone();
spawn で送ったり、
let _ = cpu_pool.spawn(Box::new(lazy(move |_| {
tx.send(1).unwrap();
Ok(())
})));
遅延関数内で送ったりすることができます
let f = lazy(move |_| {
tx_2.send(1).unwrap();
//
});
cpu_pool.run(f);
受信側の rx で普通に読めるようになります。
rx.into_iter().count()
以上、