PostThreadMessageについて

[戻る]
たけだ 2006/10/08(日) 22:55:21
スレッド-1で
イベント待ちとして、
while (1) 
{ 
        GetMessage(lpMsg, NULL, 0, 0); 
        処理
}

としておいて、スレッド-2で

PostThreadMessage(ThreadId, Msg, wParam, lParam);

のようにメッセージを投げた場合、4バイトの情報しか送信
出来ないようで、何故かと思っています。
これでは、
仮にwParam等にデータのポインタを渡したとしても、
スレッド-1側でのローカルへのデータ退避が
完了するまで待ち合わせしなくてはならず、
非同期のイベントのメリットがなくなってしまうのです。

mallocとfreeで自作してもよいのですが、
これぐらいのライブラリは
絶対何か存在するはずだと思っていますが
いかがでしょうか。

とおりすがり 2006/10/09(月) 02:01:56
いかがでしょうとか言われても…
誰か作ってる人いるかもねと答えればいいの?

Ban 2006/10/09(月) 05:06:25
4byte+4byte=8byte以下の通知で事足りることも多いですし、
それだけでメリットがなくなったりはしないと思いますけど。
っていうか、むしろ勝手にメモリ確保とかされた方が困るなぁ。

そもそも、求めてるライブラリがPostMessageのラッパーなのか、
メモリプールの話なのかも書かれてないですし、
ずばり期待にこたえるかは知りませんが、どちらにしても
「えぇ、ありますね」ってところでしょうか。

たけださんが、すばらしいライブラリを自作して公開すれば、
次に同じ事を思った人はたけださんのライブラリに感謝するかと思います。

たけだ 2006/10/09(月) 08:09:58
皆様,
さっそく,いろいろお教えいただきまして,ありがとうございます.

> そもそも、求めてるライブラリがPostMessageのラッパーなのか、
> メモリプールの話なのかも書かれてないですし、

もし,ここが,PostMessageにこだわらずに,
(もし,こだわるとするならば,やはり4バイトが限界なのですね)
メモリプール関係のライブラリから選ぶという話に
限定すれば,具体的に,どのようなものがあるのでしょうか?

Ban 2006/10/09(月) 09:06:59
多分有名なのは、C++屋さんのお約束boost.orgでしょうか。

ACEの下部ライブラリにもあった気がします。

探せばもっとありそうなのは同意。
#独自ラッパ層持ってるようなヤツには結構あるのでは。

ITO 2006/10/09(月) 19:53:52
> PostThreadMessage(ThreadId, Msg, wParam, lParam);
> のようにメッセージを投げた場合、4バイトの情報しか送信
> 出来ないようで、何故かと思っています。
メッセージとは、受取った関数で(今回はスレッド)どんな
作業をしなければいけないかというフラグみたいなものだと思います。
なので4バイトあれば十分です。
> 仮にwParam等にデータのポインタを渡したとしても、
> スレッド-1側でのローカルへのデータ退避が
> 完了するまで待ち合わせしなくてはならず、
> 非同期のイベントのメリットがなくなってしまうのです。
共有メモリーを作るのが早いんじゃない?
スレッド2つで非同期で動かすならそれなりのアクセス制御も必要です。

PATIO 2006/10/10(火) 13:22:57
メッセージに関しては皆さん書かれていますが、
4バイトが二つで足りるように通知内容を設計するのが大前提でしょう。
プロセスを跨ぐ事ができるメッセージで大量のデータを引き渡すのは
難しいと思います。まあ、ある程度までならWM_COPYDATAで引き渡せますけど、
この場合はSendMessageで同期にしないと駄目ですしね。

基本的にはスレッドあっても非同期で何かしようとするのなら
共有メモリの概念を使う必要があるという事だと思います。
スレッドだとグローバル領域が使えるというメリットがあるので
排他制御をしてくれるデータのアクセサを持った共有メモリクラスでも
作成してグローバル領域にインスタンスを作成してはどうですかねぇ。
これだとかなりお手軽にデータのやり取りができると思いますけれど。

とるまリンゴ 2006/10/10(火) 13:34:01
>4バイトの情報しか送信
>出来ないようで、何故かと思っています。


PostThreadMessage()のwParam, lParamは、ポインタなので
4バイトです。

wParamでだけを使う例ですと(※4バイト超の)メモリ確保
したポインタ(これは4バイト)を通知します。


スレッド-2
 (1) new、malloc()等で送りたいデータサイズ分
     メモリ確保してそこにデータセット
 (2) (1)ポインタをwParamにセット
 (3) PostThreadMessage()コール


スレッド-1
 (1) GetMessage()
 (2) 第1引数のwParamメンバ(ポインタ)が指す
     データ領域(スレッド-2の(1)のサイズ)を取得
 (3) メモリ開放
     (newに対してdelete、malloc()に対してfree())


> 仮にwParam等にデータのポインタを渡したとしても、
> スレッド-1側でのローカルへのデータ退避が
> 完了するまで待ち合わせしなくてはならず、

それは、PostThreadMessage()とGetMessage()に限定した狭い範囲
の話しだとそうとは限りません。

ただ、GetMessage()側スレッドのメッセージ受信処理時間より
PostThreadMessage()間隔が短かい状態が続くようなら、
メモリ・処理とも破綻しますので、この辺り破綻しないような
設計が必要です。

また、これらメッセージ授受処理を使う側の
データ授受の仕様を(自身で)はっきりさせましょう。

> 非同期のイベントのメリットがなくなってしまうのです。
これ以降の文章は何を言っているかわからない
(のと知りたくないので)、ノーコメントです。

PATIO 2006/10/10(火) 14:04:14
> PostThreadMessage()のwParam, lParamは、ポインタなので4バイトです。

> wParamでだけを使う例ですと(※4バイト超の)メモリ確保したポインタ(これは4バ
イト)を通知します。

ポインタなのでと言うのは語弊があると思いますよ。
これらは別にポインタを意味しているわけではなくて単純に二つ4バイトのパラメータを
表しているだけです。
4バイトなのでポインタの代用としても使えるというのが正確な表現でしょう。
逆に言うとポインタである必要はないはずです。

やり方的には、とるまリンゴさんの方法も不可能ではないですけれど、
安全性と言う面からするとあんまりお勧めしたくない方法だと思います。
只でさえメモリ確保と開放はきちんと管理しないとリークが発生しますし、
確保と開放が別スレッドだと間違いが置きやすいと思います。
御本人が書かれている通り、かなり限定条件が付いた上での使用になるので
限定条件を付けてまで使うより、正攻法で行った方が応用も利くと思います。

まあ、最終的にどういう方法を採用するのかは御本人次第とは思いますけれど。

> ただ、GetMessage()側スレッドのメッセージ受信処理時間よりPostThreadMessage()間
隔が短かい状態が続くようなら、
> メモリ・処理とも破綻しますので、この辺り破綻しないような設計が必要です。

ここまで考えるのであれば、普通に共有メモリを使って設計した方が良いと私は思います。

ITO 2006/10/10(火) 20:42:14
 ただ、たけださんの質問を読み返すと使い方がイベント同期でいいような感じが
します。
 わざわざ「PostThreadMessage」を使う意味が.....
 ただ共有メモリーを使わずに「PostThreadMessage」でデータ転送をしたかった
のかな?
 「WaitForSingleObject」でイベントを待って、共有メモリーのデータを処理する。
という手順でいいように思います。
たけださんがどのようなシーケンスを考えているのか分りませんが、
共有メモリーがかち合わないようにしっかりとタイミングを合わせて処理するように
すればフラグを利用した程度の排他制御でうまくいくように思えます。

たけだ 2006/10/13(金) 02:41:00
いろいろお返事ありがとうございます。
実は、これ、非同期で動かそうとしています。

ITO 2006/10/13(金) 12:41:30
>実は、これ、非同期で動かそうとしています。
うーーん、なおさら「排他制御」で守られた「共有メモリー」を利用しない
とだめですね。

PATIO 2006/10/13(金) 15:25:07
と言うわけで共有メモリとか排他とかそういう勉強をしてください。
今後もマルチスレッドでの制御を使う気があるのであれば、
どちらにしても一度はきちんと勉強しておくべきです。

Ban 2006/10/13(金) 18:58:56
理由は書かれてないのでわかりませんが、
根本的にデータ待避時間の待ち合わせをしたくないから、
(占有できるように)mallocで領域をとる云々の話なんだと思いますし、
ITOさんとPATIOさんののお話は理解されてるようにみえるます。

占有の(排他不要な)領域を確保して投げ、受け側で回収して解放したいという話で、
共有メモリを一枚プレーンに使う前提の質問ではないと理解してましたが…。

ようはバッファキューみたいなものが作りたいんじゃないでしょうか。

バッファフルで送信がとまるワーストは仕方ないとして、
毎回の待ち合わせしてたのではこの役はしないでしょう。

せめてそのメモリをリングバッファでつかうとか、プールにするとかの必要があり、
またプールから領域を取るだけならメモリ確保は片側ですみますし。

そもそもは「こういうライブラリ知りませんか」ですね。
DirectShowで提供されるフィルタ実装用バッファは、まさにこんな感じです。

Ban 2006/10/13(金) 19:02:13
あ、DirectShowの場合、メッセージ処理ではないのでGetMessageでは取れませんが。

ITO 2006/10/17(火) 20:13:38
 「HeapAlloc」で共有メモリーを作成すると排他制御がしやすいみたいですね。
関数の説明(MSDN参照のこと)を見ると書いてあります。

古いスレッドには追加発言できません。