- net tcplistner
- bindすると
- mioListnerを初期化する
- Wacher::newが実行される。
- mioのEventを監視するReactorが起動する。
- Reactor::registerで、watcher::new経由で渡ってきたmioListenerを監視対象に登録している。
- Reactorが起動すると別スレッドを起動してmain_loopに入る。
- main_loop内部でpoller::pollを実行し、監視対象からEventが来ていないかを監視。
- eventが来たらentriesからeventと紐づいたentryを取得し、eventの種類(読み込み、書き込み)に応じて対応するwakerをentryから取得、wakeを実行(この部分理解が曖昧)
- main_loop内部でpoller::pollを実行し、監視対象からEventが来ていないかを監視。
- mioのEventを監視するReactorが起動する。
- incoming.nextすると
- NextFutureが帰って来て、こいつをawaitすると、Incoming::poll_nextが実行される
- NextFutureのpropertyにstreamとしてIncomingが入っているため。
- Incoming::poll_next内部でTcpListener::acceptが実行される。
- TcpListener::accept内部でWatcher::poll_read_withが実行される。
- 引数の関数として、TcpListener::accept_stdが呼ばれるclosureが渡されている。
- closureを実行し、streamを返せるか確認。
- 返せるようであればPoll::Ready(res)を返す。これはResult<TcpStream,io::Error>である。
- Blockするよエラー以外は一番上の階層まで伝播していき、mainがResult::Errを返す。
- closureを実行し、streamを返せるか確認。
- ここで、entryにwakerが登録されていなかったらwakerを登録する(この部分理解が曖昧)。
- Readyを返せる状態でなければ最後にPendingを返し、Reactorのthreadがwaker::wakeするのを待つ。
- 引数の関数として、TcpListener::accept_stdが呼ばれるclosureが渡されている。
- TcpListener::accept内部でWatcher::poll_read_withが実行される。
- NextFutureが帰って来て、こいつをawaitすると、Incoming::poll_nextが実行される
- bindすると
- block_onすると
- 引数として渡したFutureがrunをするclosureに包まれてTask::set_currentに渡される。
- set_curretでは、現在実行中のtaskに対して割り込みして、指定したtaskを実行するようにする。
- CURRENTという現在実行中のtaskを格納するthread_local変数の中身を指定したtaskのものにして、taskが実行し終わった後で元々入っていたtaskに置き換える。
- runでは、引数としてわたされたfutureのpollを行う。
- arc_parkerをcontext経由で共有する。waker::wakeで呼ばれるのはarc_parker.unparkである。
- Poll::Pendingが帰って来たらarc_parker.parkを実行し休止状態に入る(waker::wakeが実行されると再びpollする)
- set_curretでは、現在実行中のtaskに対して割り込みして、指定したtaskを実行するようにする。
- 引数として渡したFutureがrunをするclosureに包まれてTask::set_currentに渡される。
- spawnすると
- 引数として渡したFutureがasync_task::spawnに渡される。
- async_task::spawnはscheculeclosureを受け取り、task.scheduleを実行するとschedule closureが実行される。
- schedule closure内部ではexecutor::scheduleが実行される。
- executor::scheduleでは、現在のthreadがworkerかどうか(wokerでない場合main thread扱い)で分岐する
- worker threadの場合、workerのtask queue(Wokerという名前。ややこしい)にtaskを積む。
- main threadの場合、POOLのqueueに積む。(POOLはlazyに包まれているため、初めてspawnした場合ここでPOOLが起動し、worker threadが起動する。)
- 最後にPOOLのsleeperというcondvarのnotify_oneを実行。休止状態のworkerを一つ起こす。
- executor::scheduleでは、現在のthreadがworkerかどうか(wokerでない場合main thread扱い)で分岐する
- schedule closure内部ではexecutor::scheduleが実行される。
- task.scheduleを実行。
- POOLが起動した後
- cpuの数だけthreadが起動し、thread内部でProcessorを起動する。(workerのtaskを管理する変数)
- worker threadはmain_loopを実行。
- main_loop内部ではwork_stealing方式で実行可能なtaskを探索。
- taskがあればそのままtasl.runを実行。
- set_currentでtask.runを実行。task.runではtaskに紐づくfutureをpollする(ここの挙動がよくわかっていない)
- Pendingだとすぐrescheduleしているように見えるが...(実験したところそのような挙動はしない)
- wakerを使っているのかよくわからん...
- set_currentでtask.runを実行。task.runではtaskに紐づくfutureをpollする(ここの挙動がよくわかっていない)
- ない場合、POOL.sleepersというcondvarをwaitし、休止状態に入る
- taskがあればそのままtasl.runを実行。
- main_loop内部ではwork_stealing方式で実行可能なtaskを探索。
- worker threadはmain_loopを実行。
- cpuの数だけthreadが起動し、thread内部でProcessorを起動する。(workerのtaskを管理する変数)
- async_task::spawnはscheculeclosureを受け取り、task.scheduleを実行するとschedule closureが実行される。
- 引数として渡したFutureがasync_task::spawnに渡される。
Last active
December 17, 2019 19:34
-
-
Save tawashichan/2ed3fe19d77b552647691a1f8a82a458 to your computer and use it in GitHub Desktop.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment