アペフチ

Re: Rocketでチャネルをうまく扱いたい

この前の「Rocketでチャネルをうまく扱いたい」には少し反応を貰えました。ありがとうございます。

確かに! すごい! よく気付きましたね!!

これは、mpsc::channel のドキュメント`mpsc::Sender`のAPIリファレンス読んで分かってるつもりだったのですが、指摘されると考えが進みますね。ありがたや。この前の日記では、自分でも何に釈然としていないのか分からない状態で書いていたのだなあ、ということがよく分かりました。

ポイントはこうです。

  • 全部自分で書けるならSenderclone() して、ウェブリクエストを処理する各スレッドに渡すことができる

  • RocketStateはパラメーターに SendSync を要求する(が、 SenderSync を実装しない)

    • これは多分、一般にマルチスレッド対応させるため、つまり複数のワーカー間で状態(ここでは Sender )を共有するため

  • Rocketがスレッドを作るところに割り込むことはできない

    • ので sender.clone() してスレッドに渡すことができない

ので、「(全部自分で書ければ)理論上は clone できるのになあ」という気持ちと「まあ一般的に作るフレームワークの立場としては最初からマルチスレッド対応になっている構造体を要求せざるを得ないよね」という気持ちとがぶつかってもやもやしていたのでありました。あーすっきりした。

最後の「Rocketがスレッドを作るところに割り込むことはできない」のはちょっと重たくて、実はRocketではなくて、Rocketが使うHTTPライブラリーのhyperのレイヤーの話なので(server/listener.rs#L31)Rocketに求めるのはちょっと厳しいなという気がします。特に、hyperを使わなくなることも検討されているようですし(Stabilize HTTP library · Issue #17)。

  • 自動で clone を呼ぶようなラッパー構造体を作って、

  • hyperでスレッドに変数をムーブする時に呼び出される「前処理フック」用のトレイトを作って、

  • ラッパー構造体でそのトレイトを実装させる

とかやればうまくいくんですかねえ。……それだったら SenderSyncSender に変えて使う方が楽ですよね。

Multi-producer multi-consumer channels for message passing

Channels are concurrent FIFO queues used for passing messages between threads.

Crossbeam’s channels are an alternative to the std::sync::mpsc channels provided by the standard library.

(メッセージパッシング用のマルチプロデューサー・マルチコンシューマーチャネル)

(チャネルとはスレッド間メッセージパッシングのために使われる並行FIFOです。)

(クロスビームのチャネルは標準ライブラリーで提供されているstd::sync::mpscのチャネルの代替となります。)

だそうで、crossbeam_channel::Sender のAPIリファレンス見るとしっかり Sync も実装しててRocketの State に渡せるし、いいかも。

特に、今はRustの学習という目的が大きくて「とりあえず動くようにして、後でどんどん直していこう」というスタンスでやってるからライブラリーとかあんまり比較してないで今回も取り敢えず標準ライブラリーの mpsc を使ったけど、将来的には複数のワーカースレッドを作って、チャネルはワーカー間で共有したい、という気持ちになるだろうから、その時にマルチコンシューマーというのは活きてくるはず( mpsc はコンシューマーの Receiverclone もせずに一つだけ使う)。

情報ありがとうございます。


余談ですけど、Rustでググってると(最近はDuck Duck Goを使うことも多いけど)、Redditが引っかかるのが多くて驚いています。Redditってプログラミングについて議論するイメージなかった。