C++相談室 part150

■ このスレッドは過去ログ倉庫に格納されています
2020/03/24(火) 00:04:33.93ID:YFRNwZnv
C++に関する質問やら話題やらはこちらへどうぞ。
ただし質問の前にはFAQに一通り目を通してください。
IDE (VC++など)などの使い方の質問はその開発環境のスレにお願いします。

前スレ
C++相談室 part149
https://mevius.5ch.net/test/read.cgi/tech/1581974381/
このスレもよろしくね。
【初心者歓迎】C/C++室 Ver.105【環境依存OK】
http://mevius.5ch.net/test/read.cgi/tech/1556142878/


■長いソースを貼るときはここへ。■
 http://codepad.org/
 https://ideone.com/

[C++ FAQ]
https://isocpp.org/wiki/faq/
http://www.bohyoh.com/CandCPP/FAQ/ (日本語)

テンプレここまで
2020/05/06(水) 15:40:04.68ID:g1nQsgpd
>>693
お前こそマニュアル読めよ
メモリ操作にはlockプリフィクスがつけられるんだよ
2020/05/06(水) 16:04:50.82ID:dxwAL6rC
lock prefix は、mov 命令には付けられないがな。
2020/05/06(水) 16:15:13.22ID:zSUZ9nVL
データ競合と競合状態ごっちゃにしてない?
2020/05/06(水) 16:36:19.56ID:DK2U3wBE
アトミックはいわゆるout of thin airな値の発生を防ぐためのもの
それ以上でもそれ以下でもない
2020/05/06(水) 16:50:28.87ID:8YawtAIF
std::atomic の意味付けとごっちゃになるから、「割り込み不可」「不可分」あたりと使い分けてほしいなぁ。
2020/05/06(水) 17:03:54.41ID:dxwAL6rC
もしかして、
double  g_dbl[1024];
に対して、何かの値を足すような動作を、2つ以上のスレッドで
分担して行うことで高速化しようとしているのか?
そんなやり方は、マルチスレッドプログラミングでやっていいのだろうか。
普通は、要素番号 0〜511 までをスレッド1が、512〜1023 までをスレッド2
が計算して高速化する。
全く同じ場所に複数のスレッドが書きこむことは原則としてやらないはずだ。
2020/05/06(水) 17:08:11.44ID:dxwAL6rC
>>701
GPGPUを使ったレイトレーシングでも、画面上の別のピクセルをそれぞれのコアが
計算するのが原則で、1つのピクセルを複数のコアが分担して計算するには、それなりの
工夫がいる。
工夫というのは、途中までは別のワーキングエリアに書きこんでおいて、最後に
その結果を基本的にシングルコアで足し合わせて最終結果とするようなことだ。
これだと、例えば、途中の計算を double型で行うとしても、doubleへの書き込みが
atomicであることは特に必要ない。
2020/05/06(水) 17:11:26.13ID:E/8R3YZo
>>696
そうだけどmovはそもそもatomicじゃん
>>694 で何をいいたいのかわからないな
(ちなみに最近のコンパイラはfpu命令でなくsimd使うのでmovと書いてる)
2020/05/06(水) 17:14:17.87ID:dxwAL6rC
気になったのは、「atomic」というコンピュータサイエンスで用いられている
言葉を >>611 のように実際のCPUで出来ているかどうか質問していること。
IntelのCPUマニュアルでは、atomicという言葉は使わずに、#LOCK PINアサート
が立つかどうかや、キャッシュコヒーレンシー、といった言葉で説明されている。
「atomic」という言葉は、キャッシュなどが「無いものとして分かり易く」
理解するには有効であるが、実際のCPUではキャッシュの一貫性や、PCIバス規格
と絡んだ詳細な説明が必要となる。
何を持って「atomic」というか、という問題が起きるからだ。
2020/05/06(水) 17:18:53.44ID:dxwAL6rC
>>702
movも、実際のCPUでは必ずしもatomicとは限らない。
まず、alignment 境界を跨いででいるような場合や、
物理的に複数のCPUがマザーボード上にある場合のキャッシュの一貫性の問題が
あるから。
Intelの最適化マニュアルなどで、マルチコア並列化の例として上がってないような
方法は、勝手にやると破綻するかもしれない。
実機で実験してやるのは自由だが、他の人のCPUでは誤動作するのは覚悟した方がいい。
「アメリカ人は、書いてないものを勝手に使ったあなたが悪い」
という思想だぞ。
2020/05/06(水) 17:31:25.73ID:E/8R3YZo
>>704
マニュアルに安全な具体例として載ってないから疑ってるって話ね
ご自由にどうぞ
でもそれはあくまでお前の判断
メジャーコンパイラがintelのサポートうけてないとは思えないから
おれはコンパイラの出力眺めてみるけどね
2020/05/06(水) 17:39:01.96ID:dxwAL6rC
>>705
並列化の処理は研究されているから、Intelが例として一度も書いてないんだったら
多分やめた方がいいと思う。
2020/05/06(水) 17:49:26.97ID:+O5RjP+P
>>703
atomicとコヒーレンシーや同期がごちゃまぜになってる

もうちょっと勉強するか
素人なら素直に既にある同期や排他制御の仕組みを使いなさい
2020/05/06(水) 17:51:54.81ID:+O5RjP+P
色々な理由でやむを得ず使う上級者の技を
素人がまねしなくて良い
2020/05/06(水) 17:57:11.74ID:E/8R3YZo
>>706
ちなみにメジャーコンパイラが
std::atomic<double> & std::memory_order::relaxed
をどう展開するか知ってるんだよね?
これを疑ったらコンパイラを自作するしかないんでは?
2020/05/06(水) 18:31:40.49ID:dxwAL6rC
>>709
そのoperator=()関数は、store() 関数を使っていて、その関数は lock(), unlock()
で囲ってから書き込みをしている。
2020/05/06(水) 18:56:13.77ID:E/8R3YZo
>>710
そりゃご愁傷様
おれの環境だと普通にmovqだけどね
2020/05/06(水) 18:57:46.10ID:dxwAL6rC
>>711
だったらそれでいいじゃない。
2020/05/06(水) 19:17:44.45ID:E/8R3YZo
>>712
おれは最初から困ってないしw
お前がいろいろ大丈夫かよ
2020/05/06(水) 19:18:48.57ID:dlDgLyfe
ちょっ(キャッシュの)一貫性とアトミック(なアクセス)は別概念なのでは…
後者はあくまで>>664の括弧内の意味
一貫性が保証されている単一キャッシュライン内のデータに対するアクセスでも
アトミックでないケースが理論上はありえる
2020/05/06(水) 19:19:22.45ID:ZjhSP/3u
なんで揉めてんだか訳わかんね
2020/05/06(水) 19:21:46.08ID:dlDgLyfe
つか同一キャッシュラインに乗っているからといって
配列アクセスは非アトミック、
2020/05/06(水) 19:23:51.44ID:dlDgLyfe
>>679
じゃあ電話交換機のプログラマーとか?

災害に際して実際に活躍したシステムの例を引き合いに出したのに
なんで白昼夢スレに誘導されるのかがわからん…
2020/05/06(水) 19:44:30.16ID:6g3bWVkt
C++でdoubleで同期取ろうとしてることすら意味不明なんだがキミたちは結局何がしたいんだい? 
処理系依存するものはOSの同期を使えよ。
2020/05/06(水) 19:47:35.61ID:S060FgXU
>>703
atomicっていう言葉は使われてるが
https://xem.github.io/minix86/manual/intel-x86-and-64-manual-vol3/o_fe12b1e2a880e0ce-258.html
2020/05/06(水) 19:48:49.83ID:kak2WxQU
同期がめっちゃ遅いから困ってんだってよ
2020/05/06(水) 19:55:48.41ID:6g3bWVkt
同期は遅くて当たり前だろ。
並列化したら速くなるとか同期コスト知らないIT音痴の妄想なんだから。

処理系依存していいならIntelのTSX試せよ。
2020/05/06(水) 19:58:00.21ID:DK2U3wBE
同期を速くするのは無理だぞ
高速化したければ同期を減らすんだぞ
2020/05/06(水) 20:12:52.44ID:E/8R3YZo
>>718
できるかどうかと
やるべきかどうか
は別の話
区別しようぜ
724843
垢版 |
2020/05/06(水) 21:51:51.19ID:U6CLxvSb
Atomicの話と同期の話の区別も宜しくねw
2020/05/06(水) 22:20:21.87ID:+O5RjP+P
>>718
誰もdoubleで同期を取るなんて話はしてない
atomicなアクセスの話題

>>716
複数ならSIMDレジスタを使う
YMMなら4個、ZMMなら8個までatomic
2020/05/07(木) 00:01:22.08ID:hoUWiCnf
同期をとればatomicである必要はない
そういうことじゃないのか
2020/05/07(木) 00:24:54.15ID:N8w6+mz8
話をまとめるとこうなる。

・8byteの読み書き命令がatomicかどうかは処理系依存する話でC++の話ではない。スレチだが聞くならチップを指定して聞け。チップ仕様見れば答えは出る。議論の余地はない。
・8byteの読み書きを同期したい、atomicにしたい。OSの同期か適当な同期ライブラリ使え。悩む余地なし。
・atomicと同期は話は別だ →ありえないw ハードでatomic命令の実装に同期が必要だし、ソフトの同期処理の実装にCPUのatomic命令を使う。atomicの実装を知りたければVHDLスレにでも行け。
・馬鹿は同期を理解できない←30年前から言われてる名言。C++スレでdoubleがatomicかというアホ質問自体が証左。
2020/05/07(木) 01:03:56.90ID:M+iqUPlL
EOF
2020/05/07(木) 01:11:02.02ID:0pZrsm5h
>>719
なんだ、そこにそのまま書いてあるじゃない。
つまり、alignされているなら quadword は atomically に Read/Write できる。
キャッシュラインの中に納まっているなら align されてなくても OK、と。
8.1.1 Guaranteed Atomic Operations
The Intel486 processor (and newer processors since) guarantees that
the following basic memory operations will
always be carried out atomically:
・Reading or writing a byte
・Reading or writing a word aligned on a 16-bit boundary
・Reading or writing a doubleword aligned on a 32-bit boundary

The Pentium processor (and newer processors since) guarantees that
the following additional memory operations will always be carried out
atomically:

・Reading or writing a quadword aligned on a 64-bit boundary 16-bit accesses to uncached memory locations that fit within a 32-bit data bus

The P6 family processors (and newer processors since) guarantee that the following additional memory operation will always be carried out atomically:
・Unaligned 16-, 32-, and 64-bit accesses to cached memory that fit within a cache line.
2020/05/07(木) 06:07:03.34ID:cLsDnrKi
>>611に対する回答は既に>>673で明確に示されて終わってる話。
それを急に同期の話と勘違いしてとんちんかんな蒸し返し方をした>>680がおかしい
2020/05/07(木) 06:35:21.80ID:N8w6+mz8
その486の話でいうと、当時、486は自己書き換えコードを駆逐した。Prefetchされたコードは非同期のまま実行されたからだ。Prefetchされたものはメモリではないと言い訳してもPGはそうは思ってないのだから高速なCPUだけ動かないコードがいっぱいあったわけだ。
結局、Intelが折れたのかPenから正しく同期されるようになった。TSXといいIntelも結構やらかしてるし、PICじゃ今でも同期エラッタてんこ盛り。MIPSの実装なんて言わずもがな。
2020/05/07(木) 06:52:28.04ID:Xvq6sZ7Q
同期って用語の使い方に違和感があるなあ
733843
垢版 |
2020/05/07(木) 07:35:15.71ID:/g81R4QF
>>732
同意
そもそも486の時代に自己書き換えコードがいっぱいあったとかにわかに信じがたい
2020/05/07(木) 08:02:12.59ID:wkYaXeHy
8086時代は結構あった
古いコードのおもりをさせられた人は苦痛だったろうね
今よりはるかにパズルコードが多かったし
2020/05/07(木) 08:27:36.65ID:N8w6+mz8
>>730
atomic命令=排他制御(同期処理)された命令。同義。
doubleアクセスがatomicか知りたい=double値で同期したいと解釈するのは普通じゃないかな。
まぁatomicであろうとなかろうと、C/C++的にはOSの同期オブジェクト使えって結論になるわな。
マルチスレッドの再現性ないバグの99%は同期のおれおれ実装が原因だし。
736843
垢版 |
2020/05/07(木) 09:26:23.94ID:rgMcdocw
アトミックと排他制御と同期処理って同じじゃねーぞ
doubleでアトミックと言うのは例えば
double d = 1.23;

d = 2.34;
ってやった時にdが1.23と2.34以外の値にならない事を言う
どっちの値になるかまでを保証するわけじゃない
2020/05/07(木) 09:34:04.25ID:qJNaSSxu
何に基づいた主張なのかわからない
論拠も書くべき
2020/05/07(木) 09:50:51.36ID:N8w6+mz8
>>736
おれは同じ意味で使ってるし、
世界の技術者もそうだからボクたちに合わせてくれないかな。
2020/05/07(木) 09:53:56.60ID:Uptrp4d8
>>735
> まぁatomicであろうとなかろうと、C/C++的にはOSの同期オブジェクト使えって結論になるわな。

お前 ID:lE4/XlkX だよね?
740843
垢版 |
2020/05/07(木) 10:01:49.95ID:EiluKhsY
>>738
> おれは同じ意味で使ってるし、
それは勝手にしてくれ、どうせ人の言うことを聞かないだろうし
> 世界の技術者もそうだから
妄想乙w
2020/05/07(木) 10:21:20.74ID:N8w6+mz8
>>739
単発IDのくせにいなきり「お前」かよ。GWはほんと口の聞き方も知らないリアルクズ野郎ばかりだな。
おまえのような礼儀も知らず妄想しかできない低能クズに寛容なるおれ様が特別に教えてやろう。

違いますよ^^ 礼儀を知らない馬鹿は二度とおれにレスすんなw
2020/05/07(木) 10:32:16.12ID:PvsEcGe8
同期とアトミックと排他制御が同じとは
ヤバいのがいるなこのスレ

ソフトウェアの基礎を学んだ方が良い
2020/05/07(木) 10:36:17.88ID:0pZrsm5h
個人的に並列化処理といえば、例えば2coreの場合、
double buf[1024];
の内の、0-511 までを core1、512-1023 までを core2で処理するものだと思っていた。
atomicであるかどうかを気にしている人は、
buf[0] を core1とcore2で
[core1]
for(・・・) {
 buf[0] += 1.0;
}
[core2]
for(・・・) {
 buf[0] += 1.0;
}
みたいに同時に書きこみたいと思っているの????
でも、atomicというのは、書き込みのみ、または、読み込みのみ、のどちらかの
場合だと適用できるけど、↑のコードの場合、+= 演算子は、直前の値を読み取ってから、
1.0 を足して、同じ場所に書きこむ動作をするので、いくら、double値の書き込みが
atomicであっても、結果はめちゃくちゃになるよ。
2020/05/07(木) 10:45:35.17ID:Uptrp4d8
>>741
- std::atomicの使いどころを理解してない
- "OS"の同期プリミティブを使えと主張 (なぜOSと限定?)

この二つの条件を満たす別人が現れる確率は結構低いと思ったんでね
非礼の詫びとしてatomicの使いどころ知りたかったら教えてやるけどどう?
2020/05/07(木) 10:50:13.38ID:Uptrp4d8
>>743
そんなraceばりばりの例だめにきまってんじゃん
単純に一方がwriter、他方がreaderでもatomic性は必要でしょ
746843
垢版 |
2020/05/07(木) 11:13:09.18ID:lQhGrp4h
>>743
> atomicであっても、結果はめちゃくちゃになるよ。
+= の話はレイヤーが違う
2 threadで元々0.0の変数に各々 += 1.0を10回実行した時に結果が20.0増えないことがあるって言う話をしてるんだろうけど結果は1.0~20.0に範囲になる
>>611のは浮動小数点フォーマットとして正しいかどうかもわからん
2020/05/07(木) 11:20:48.41ID:Xvq6sZ7Q
std::atomic<double>はoperator+=ないね
2020/05/07(木) 12:09:28.57ID:0pZrsm5h
>>746
>>611のは浮動小数点フォーマットとして正しいかどうかもわからん
それも、個人的には分かっているつもり。
2020/05/07(木) 12:11:04.76ID:0pZrsm5h
>>745
>単純に一方がwriter、他方がreaderでもatomic性は必要でしょ
確かに必要だね。
でも、個人的には具体的にどういう利用例があるのか分からない。
750843
垢版 |
2020/05/07(木) 12:17:56.15ID:FtlEpNqJ
>>748-749
書き込みスレッドが書き込んでいるデータを読み出しスレッドが読み出して表示する
とかの場合アトミックでないと不正なデータを表示してしまう
計測器等でありがちな処理だよ
2020/05/07(木) 12:53:58.73ID:N+2vUAWE
>>749
一番原始的なスレッド通信

>>743
複数命令を使って事実上アトミックに出来るCPUもあるし
整数ならアトミック加算出来る命令があるCPUもある

ARMやMIPSは前者、x86は後者
2020/05/07(木) 17:00:45.03ID:jqbAFx8V
C++に限ったことじゃないかもしれないんですけど質問させてください
typedefで型に別名つけることについてです。今いじってるコードでたとえばvector<animal>にanimalsって型名をつけるようなのが山のようにあるんです
これすごくわかりにくいなと思います。例えばvector<animals>で宣言されてればその変数にどんな操作ができるのか一発ですが突然animalsで宣言されても何ができる型なのか初見では分かりません
別名をつけることがメリットになることってあるんでしょうか
753デフォルトの名無しさん
垢版 |
2020/05/07(木) 17:14:48.12ID:8jv+kISL
メリットは君が言ってる通り特定の言語に限った話では特定の回答は出て来ないし
言語を取り巻く環境(エディタや統合環境や諸々)でも答えは変わってくる
2020/05/07(木) 18:04:16.36ID:VS6AE9q5
>>752
using animals = std::vector<animal>;
わたしも、こういう typedef はしない方ですね、リッチなエディターを使っていないせいかもしれません
書いた人は別名を細かく付けた方がいいと考えているようですが、こういうのは記述の粒度の問題かもしれませんね
2020/05/07(木) 18:08:47.80ID:cLsDnrKi
>>752
例えば後からvectorじゃなくてlistにしたいなーと思ったときに修正箇所が一箇所で済む
756デフォルトの名無しさん
垢版 |
2020/05/07(木) 18:14:03.65ID:V086WOzl
テンプレートで使うからでは。
2020/05/07(木) 18:29:01.78ID:0pZrsm5h
>>752
書くのが簡単になり、見るのも分かり易くなることがある。
また、animal_s とちゃんと最後に複数形を現す「_s」を付けるという
自分なりの命名規則を付けておけば、vector<animal> のことである
こともすぐに分かる。
758デフォルトの名無しさん
垢版 |
2020/05/07(木) 18:31:07.04ID:0pZrsm5h
>>757
なお、型名は小文字ではなく、Animal か、CAnimal、TAnimal のようにするのが慣例。
vector<Animal> の場合、AnimalVector とすると、書くのも理解するのも楽になる。
templateのままをコード中に大量に書くとわずかな書き間違いで変な動作になりかねない。
2020/05/07(木) 18:36:04.65ID:0pZrsm5h
>>758
templateは、C++の中でも最も複雑で、書き間違えたときのエラーが理解しにくい
とされる部分。
だから、vector<Animal>とコードのそこかしこに書きまくるのはお勧めしない。
それと、<や> は、キーボードの配置からして打ち込みにくいという事情もある。
指が届きにくい場所にあるというか。
また、vector<Animal
と> を書き損じたような場合、>を探してコンパイラが変な場所でエラーを出して
しまい、どこでエラーが始まったか探し出すのに苦労するようなこともある。
だから、このような「組み立てられた型」は、毎度毎度そのまま使うと痛い目に
遭う可能性があるので、animals と typedef した人は賢い。
2020/05/07(木) 18:37:12.86ID:N8w6+mz8
>>744
レスするなと言ってるのにほんと人の話を聞いてないな。だから別人だって言ってるだろう。
std::atomicの使いどころってstd::atomicの話題に一度もレスしてないし、std::atomicの話を振られてもいない。

しかもOS限定とか妄想そのもの。
> OSの同期か適当な同期ライブラリ使え。悩む余地なし。
と最初に言ってる。逆にキミのその発言で、キミは今まで禄にコードを書いたことのない糞ガキの学生ということがよくわかったよ。

仮にOS提供の同期機構かstd::atomicかという選択であっても1nmもstd::atomicの選択余地はない。0%だ。
枯れてないライブラリは論外。同期バグはOr****やIntelでもやらかすし、枯れてるほうを使う。
何十年もカーネル開発者が注力し、コキ使われてきた実績のある同期コードを選ぶのがまともな社会人。
キミのような無責任な子供やテストしないOSSな人じゃないからね。OS提供がなくても同じ。
組み込み系ならチップメーカーが提供する同期ライブラリを使う。
2020/05/07(木) 18:39:12.04ID:0pZrsm5h
命名規則は、animals よりも、
vector<animal> の時には、AnimalVector
list<animal>の時は、AnimalList
とするのがお勧め。
最後の s だけだと、見落とす可能性があることと、集合体であることだけは
分かっても、それが、どんな種類の集合体かまでは分からないため。
2020/05/07(木) 18:42:48.91ID:0pZrsm5h
もうひとつ、vector<animal> より、AnimalVector とした方がいい理由は、
正規表現検索する場合のため。
正規表現だと、< や > は何らかの meta 表現的な意味を持っている場合があるかも
知れないので、型名は単純な alphabet 列の方が何かと便利。
2020/05/07(木) 19:54:24.58ID:RMklkh4T
今どきシステムハンガリアンもどきなんてやだよぅ
2020/05/07(木) 20:03:35.58ID:wkYaXeHy
vectorからlistに変えられなくなる
2020/05/07(木) 20:14:04.24ID:k+gNGLxR
>>761
vector から list に変えるときに、名前もいちいち変えないといけないのだったら、その命名ルールは今いちですね…
766デフォルトの名無しさん
垢版 |
2020/05/07(木) 20:56:23.62ID:V9Hy6a5I
Animalsの話題はわたくしがC++最大の謎と呼ぶvector継承不可問題だ
Javaだと「class Animal extends ArrayList<Animal>{」とできる
でもC++だとvectorそのものの継承はデストラクタの関係で認められていない

つまりクラスを作るかtypedefするか、C++には2通りの解決方法が存在する
2020/05/07(木) 21:04:23.79ID:+JcfXk10
自分作りゃいいだろ
コンテナくらい
2020/05/07(木) 21:04:44.42ID:Gk4UMZDB
別にvector継承してもいいんだよ
protectedかprivate継承する分には何の問題もない
役には立たないけど
769デフォルトの名無しさん
垢版 |
2020/05/07(木) 21:07:22.98ID:qT/QDoOR
この程度でs付け忘れるとか不注意にもほどがある
2020/05/07(木) 21:10:02.94ID:QyPqnZke
いや、vectorは今となっては継承すべきでないってこともないだろ
2020/05/07(木) 21:21:54.60ID:hoUWiCnf
vector<>のデストラクタが仮想でないのは仕様の欠陥ですか?
2020/05/07(木) 21:30:23.98ID:8B1BhNza
注意深さに自信があるならデストラクタが virtual でないクラスを public 継承しても
それ自体は言語仕様には反しないけど、人間は間違うのでな……。

>>768
private 継承した上で外部から呼び出しを許すメンバ関数は using すればいい。
役に立たないということはないと思う。
2020/05/08(金) 01:16:40.31ID:Fn7VYFHg
基本的なことだと思うけどよく
よくあるイベントループってどうやったらシンプルかつMT安全かつ効率的に実装できる?
次のような条件で
- qeueuが空ならwaitする
- qeueuにイベントが追加されたら直ちにおきてdispatchする
- dispatchに長い時間かかることもありえる
- add_eventは可能な限り短い処理で完了する。
- stopがよばれたらloopから直ちにぬける。dispatch中の場合は終わってから抜ける。

次に雰囲気コード書きます。
2020/05/08(金) 01:21:33.28ID:Fn7VYFHg
loop()がこれではいかんのはわかってるけど、どうすれば簡潔に書けるのかわからん
他にもあやしいところがある気がする

bool running = true;
std::deque<int> unsafe_queue;
std::mutex mtx;
std::condition_variable cond;
using unique_lock = std::unique_lock<std::mutex>;
void stop() { running = false; }
void add_event(int i)
{
  unique_lock _(mtx);
  unsafe_queue.push_back(i);
  cond.notify_one();
}
void dispatch(int) { /*do something*/ }
void loop()
{
  unique_lock lock(mtx);
  while (running) {
    cond.wait(lock, [] { return !unsafe_queue.empty(); });
    auto ev = unsafe_queue.front();
    unsafe_queue.pop_front();
    dispatch(ev);
  }
}
2020/05/08(金) 03:21:51.97ID:7git1+gm
まずconcurrent_queueを持ってくるなり作るなりして用意した方がいいよ
イベントループにロックやイベント混ぜて書くとわけわからなくなる
2020/05/08(金) 03:34:19.21ID:7git1+gm
イベントって同期イベントね
2020/05/08(金) 03:38:35.90ID:FOXu+lyu
concurrent_queueは必要ないと言うかこの用途だと無駄な処理増えるだけじゃね
778843
垢版 |
2020/05/08(金) 05:40:01.72ID:JnpjOAnv
>>773
BlockingCollection使えばいいだけじゃねーの?
2020/05/08(金) 06:51:21.78ID:M/JmLjh0
>>774
それ、イベント発行しないと止まらなくね?
2020/05/08(金) 11:45:01.04ID:Fn7VYFHg
>>775
concurrent_queueって標準であります?どれのこと?
MT安全なqueueクラスを作ると
イベント待ちしてるときのstopで即終了が面倒かなと思いました
2020/05/08(金) 12:06:11.41ID:Fn7VYFHg
>>779
そうなんですよね
runningのチェックって一回のままで実現できないですかね?
2020/05/08(金) 12:18:21.10ID:Fn7VYFHg
>>778
BlockingCollectionってどこにあります?
ぐぐったらC#のクラスは見つかりましたが
上に書いた通り、stop時の処理がまわりくどくなりそうなのを気にしてます
実行時のロジックがシンプルなやり方を追求したいです
783843
垢版 |
2020/05/08(金) 12:23:41.84ID:UXU8nfWQ
>>782
> BlockingCollectionってどこにあります?
> ぐぐったらC#のクラスは見つかりましたが
触れちゃ駄目な人だったか…
2020/05/08(金) 12:39:35.76ID:N+8ZKU+/
普通は終了を意味する番兵オブジェクトを用意するんじゃないの
キューの中身を最後まで処理して欲しいなら単に番兵を積めばいいし、無理矢理終わらせたいならキューを強制的に空にしてから番兵放り込めばいい
2020/05/08(金) 13:50:27.60ID:Fn7VYFHg
>>784
なるほどそれだときれいに書けますね
runningフラグは不要にできると

しかしわりとクリティカルな処理を想定してるので
stopを呼ぶスレッドで(イベントオブジェクトの)解放処理が起るのは問題に
なるかもしれないです(例ではintですが実際はもうちょっと凝った構造体)
runningフラグ前提だときれいに書けないですかね?
2020/05/08(金) 17:13:05.00ID:+t+L26mC
こんなんでいいのでは。running2回チェックは避けられそうにないなあ。チェックよろ
start() {
{
lock()
running = true
}
run(loop)
}
stop() {
{
lock()
running = false
}
notify()
join()
}
loop() {
lock()
while(true) {
cond_wait(!empty() or !running)
if (!running) {
break
}
pop()
}
}
2020/05/08(金) 17:29:10.43ID:NOJZfKLR
スレッド動作トリガーはcond 1個にして
スレッド内で、キューやrunningフラグを見る
2020/05/08(金) 17:32:31.56ID:NOJZfKLR
Windowsみたいな高機能な同期が有れば
イベント、タイマー、ファイルアクセス、ネットワーク通信
などなど色々な物を同時にトリガーに出来る

linux系はその辺が貧弱
スレッドを動かす為のスレッドが必要になったりする
2020/05/08(金) 17:46:30.97ID:+t+L26mC
>>788
全部selectやepollでまとめて待てるけど、winはもっと高機能なん?
2020/05/08(金) 18:43:53.40ID:NOJZfKLR
yes
2020/05/08(金) 19:10:58.40ID:Fn7VYFHg
>>786
インデントつけました

void loop() {
  lock()
  while (true) {
    cond_wait(!empty() or !running)
    if (!running) {
      break
    }
    pop()
  }
}

cond_waitの前にrunningみなくて大丈夫ですかね?
startの直後loopが始まる直前でstopが呼ばれた場合cond_waitって起きます?
2020/05/08(金) 19:27:16.63ID:V12mYFi1
>>790
違いは同期オブジェクトを含められるかどうかぐらいでは?
それ以外ならlinuxでもたいていfdになってる
少なくとも>>788の後ろ三つは可能
イベントもパイプで代用できることが多い
2020/05/08(金) 20:07:48.20ID:DADrWmcq
>>791
cond.waitはブロックする前に一度条件式を確認する動きになってる。
条件式が初めからtrueであればそもそもブロッキングをしないからcond.waitの前にrunningをみなくても大丈夫だと思う
2020/05/08(金) 20:36:08.72ID:Fn7VYFHg
>>793
そうでしたか
ありがとう
■ このスレッドは過去ログ倉庫に格納されています
5ちゃんねるの広告が気に入らない場合は、こちらをクリックしてください。

ニューススポーツなんでも実況