Closed manabinohibi closed 2 years ago
@baycedar
すみません,教えてください.
std::future
は値を1つのスレッドからしか受け取れない,であっていますか?
そうだとするとstd::future
をスレッド数分用意することになる?と思いましたがそれは違う気がします.
いえ,それであっています.std::future
は対となるstd::promise
から値を受け取るので,複数のスレッドからstd::future
を受け取るには複数のstd::promise
が必要になります.これの152-162行目と179-183行目がマルチスレッドでの使い方の例になるかと思います.
ありがとうございます.
メインプロセスを止めておく役割はstd::shared_lock
が担っているのでしょうか?
各スレッドがロックを取るのでメインプロセスがロックを取ろうとすると取れずにストップする,みたいな感じですかね.
そうですね,ロックでメインプロセスを止めています.このコードは今見ると割りと雑にやっている(1ms待てばワーカスレッドの誰かはロックを取っているだろうという曖昧な想定)のですが,ちゃんとやるなら各スレッドに2つのstd::promise
を渡して,1つを同期用(ワーカ準備完了の通知),もう1つを返り値用にするべきでしょうね.
この辺の同期は実際はグローバル変数を使ってもできます(std::atomic_bool are_ready[kThreadNum]
みたいな配列を用意すればいける)が,それをやろうとするとメインプロセスで配列を走査してfalse
がいたらsleepみたいな処理を書く必要があって,std::promise
とstd::future
はちょうどその機能を標準ライブラリ側で提供してくれている感じですね.
ありがとうございます.あげていただいたソースコードを真似ていたらよくわからぬままテスト通りました(?).
std::condition_variable
で各スレッドを待機させているんだと思いますが,これがあるならfutureいらないのでは?となったのですが,どう違うんでしょう?
今回のケースはstd::condition_variable
を使うまでもないんでしょうか.
std::condition_variable
は,ロックによる処理同期の標準実装ですね.内部的にやってることはグローバルロックでスレッドを同期しているだけで,1点違うのはスレッドの開始タイミングをnotify
である程度操作できるところです.単にロックで止めるだけだといつスレッドが再開するかはカーネルしだいなので再開のタイミングにラグが生まれるのですが,こちらを使えばそのラグを多少減らせ(ると信じて使って)ます.なお,基本的にある単一のスレッドから他の1つ以上のスレッドに対してnotify
を送るような使い方になる点には注意してください.
(どんなテストをしてたかだいぶ記憶があやふやですが)今回のテストでも確かワーカスレッドをロックで待たせていたと思うので,メインスレッドからワーカスレッドを再開させる際にはstd::condition_variable
が使えると思います.それはそれとして,ワーカスレッドからメインスレッドに向けて情報を送る場合はstd::promise
とstd::future
も必要になります.
どうもありがとうございます.
std::promise
とstd::future
が無くても通ったので,一度見てもらってもいいでしょうか.
レビュー投げます.
同時に問題点も見つけたので,それもそちらで相談します.
複数スレッドで異なる記述子を取得したいが,実際は同じ記述子を取ってきてしまう. 原因はおそらく2つ目以降のスレッドが記述子を取得する前に1つ前のスレッドが終了しデストラクタにより
is_reserved
がfalse
になるから.なので,各スレッドで取得が完了しても終了しないように待機する必要がある.
futureとpromiseを使うと良いです.