WaitForSingleObject( ..., 0 )は、リセット作用がある?

[戻る]
おもち 2008/02/18(月) 22:20:16
早速で恐縮ですが、下のコード時、
「最下行のWaitForSingleObject()から返った時は、リセット(非シグナル)状態」
でしょうか?( 各APIは、全て処理が成功しているものとします )

HANDLE h( CreateWaitableTimer( NULL, FALSE, "" ) );
LARGE_INTEGER DueTime;
DueTime.QuadPart = -1LL; // 100ns後に即シグナル化
SetWaitableTimer( h, &DueTime, 0, NULL, NULL, FALSE );
Sleep( 1 ); // 1ms待機.故に,タイマはシグナル状態
WaitForSingleObject( h, 0 );

私は「リセット状態ではない」と思っています。
「第2引数が0なので、シグナル状態の検査"のみ"を行う機能になっている。
従ってシグナル化待機と自動リセット(非シグナル化)はされない」
と考えた為です。
が、同僚は「リセット状態」という意見でした。

テストプログラムでもよく分からなかった為、皆様に意見を伺った次第です。
どうぞ宜しくお願い致します。

おもち 2008/02/18(月) 22:23:34
環境の記載を忘れておりました。
WinXP Pro. + 最新パッチ、VC++8

失礼しました。

wclrp ( 'o') 2008/02/18(月) 22:36:35
CreateWaitableTimerを知らないので推測

DueTimeを数秒にして
for(int i = 0; i < 10; ++i) {
Sleep( 1 );
w = WaitForSingleObject( h, 0 );
TRACE("%d\n",w);
}
にすればいいんじゃない。
自動リセットなら数秒後に一度だけw=WAIT_OBJECT_0で
あとはw=WAIT_TIMEOUTじゃないのかな。
手動リセットなら始めw=WAIT_TIMEOUTで
数秒後はずーっとw=WAIT_OBJECT_0じゃないのかな。

wclrp ( 'o') 2008/02/18(月) 22:37:21
秒のケタ間違えてた

玲音 (st.lain) 2008/02/19(火) 10:37:51
びみょ〜な単位時間でのタイマーの扱いは不慣れなので、ちょい不安ですが。

> HANDLE h( CreateWaitableTimer( NULL, FALSE, "" ) );
最後の""って大丈夫でしょうか? 空文字の場合はNULL指定の場合の名前なしと
別の扱いを受ける気がします。(結果に対しての影響はないハズですが)

> DueTime.QuadPart = -1LL; // 100ns後に即シグナル化
-1Lの誤記、カナ?

> Sleep( 1 ); // 1ms待機.故に,タイマはシグナル状態
コメントに書いてあるように、このステートメントが完了した時点でシグナルな
はずなので、WaitForSingleObject()はWAIT_OBJECT_0が返るのでは、と予測
します。

> テストプログラムでもよく分からなかった為
よく分からなかった、とはどゆ意味でしょうか?


# 100ns, 1msのような短時間での検証の必要性はあるのでしょうか? 
# 特にそのようにする必要がないように思われます。

玲音 (st.lain) 2008/02/19(火) 10:39:38
>> DueTime.QuadPart = -1LL; // 100ns後に即シグナル化
> -1Lの誤記、カナ?
LONGLONGの時って、LLと書けたのですね。初めて知りました m(_"_)m

ITO 2008/02/19(火) 11:41:03
「WaitForSingleObject( h, 0 );」について、
MSDN CDより、
> 0 を指定すると、この関数は指定されたオブジェクトの状態を調べ、
> 即座に制御を返します。
別に「リセット状態」とか「非リセット状態」とか関係なく、
待たずにすぐ制御を戻すだけだと思います。
後は戻り値で判断ですね。
WAIT_ABANDONED、WAIT_OBJECT_0、WAIT_TIMEOUT、WAIT_FAILED
詳細は、MSDN CDを参考してください。

> Sleep( 1 ); // 1ms待機
1msは間違えです。少なくとも10mS以上は掛かります。
(マイクロソフト承認)

> 従ってシグナル化待機と自動リセット(非シグナル化)はされない」
> と考えた為です。
> が、同僚は「リセット状態」という意見でした。
「CreateEvent」のパラメータ設定が手動で、かつ「WaitForSingleObject( h, 0 );」
でシグナルを認識したならば、「リセット状態」になる可能性があります。
きちんと手動でリセットしなければならないのであれば、一様「ResetEvent」は
入れておく必要があります。

> Sleep( 1 ); // 1ms待機
するならば、
「WaitForSingleObject( h, 10 );」
でWAIT_TIMEOUTかどうか調べるだけでいいと思います。

シャノン 2008/02/19(火) 12:23:43
やってみりゃーいいじゃないのー。

以下のように修正して実行。

HANDLE h( CreateWaitableTimer( NULL, FALSE, NULL ) );
LARGE_INTEGER DueTime;
DueTime.QuadPart = -1LL; // 100ns後に即シグナル化
SetWaitableTimer( h, &DueTime, 0, NULL, NULL, FALSE );
Sleep( 1 ); // 1ms待機.故に,タイマはシグナル状態
DWORD dw = WaitForSingleObject( h, 0 );
dw = WaitForSingleObject( h, 0 );

1回目のWaitForSingleObjectの戻り値はWAIT_OBJECT_0、2回目は WAIT_TIMEOUT となりま
した。
従って、1回目のWaitForSingleObjectから戻った時点では非シグナル状態、ということに
なります。

…これじゃダメなの?

PATIO 2008/02/19(火) 13:27:41
とりあえず、

> テストプログラムでもよく分からなかった為、皆様に意見を伺った次第です。
> どうぞ宜しくお願い致します。

シャノンさんが提示されているような方法でわかるはずなのに
なぜ解らなかったのかの方が興味あります。
ぜひ説明をお願いします。

おもち 2008/02/19(火) 14:00:52
[[解決]]
結論は「WaitForSingleObject( ???, 0 )は、非シグナル化(リセット)しない」で、当初
の予想通りでした。冒頭のコードに下記を加えるだけの簡単な検証で出来ました。
wclrp ( 'o')さんの回答に酷似した結果です。

while( 1 ){
switch( WaitForSingleObject( hTimer, 0 ) ){
case WAIT_ABANDONED:
OutputDebugString( "WAIT_ABANDONED\n" );
break;
case WAIT_OBJECT_0:// シグナル 検出
OutputDebugString( "WAIT_OBJECT_0\n" );
break;
case WAIT_TIMEOUT:    // 非シグナル(リセット) 検出
OutputDebugString( "WAIT_TIMEOUT\n" );
}
}

数十回実行後の表示結果を纏めると下のようになりました。
・まず数回WAIT_TIMEOUT。表示回数は実行毎に変動
・直後に1回だけWAIT_OBJECT_0。
・その後はずっとWAIT_TIMEOUT。
上記ループ直前のWaitForSingleObject()を削除すると、期待通りWAIT_TIMEOUTのみでし
た。

とあるH/W(MS製SDK(Win32API互換)が実装されてる非PCマシン)でも、同じような動きでし
た。

>最後の""って大丈夫でしょうか? 空文字の場合はNULL指定の場合の名前なしと
>別の扱いを受ける気がします。(結果に対しての影響はないハズですが)
今回の実験では問題外故、適当な引数にしました。
因みにPCでは大丈夫です。が、上記の"あるH/W"では、CreateWaitableTimer()がNULLを返
します。

># 100ns, 1msのような短時間での検証の必要性はあるのでしょうか? 
># 特にそのようにする必要がないように思われます。
必要です。極めて短い時間を取り扱う案件の為です。

>待たずにすぐ制御を戻すだけだと思います。
全くその通りでした。

>1msは間違えです。少なくとも10mS以上は掛かります。
未だにそうなのですね。MSDNに載ってなかった為、改善済だと思いました。
情報元を探してみます。OSにより仕様が違う可能性もありますし...。

>「WaitForSingleObject( h, 10 );」でWAIT_TIMEOUTかどうか調べるだけでいい
いえ、今回は「WaitForSingleObject( h, 0 )がシグナル状態の検査"以外"の処理をする
か?」だけを知る必要があったんです。

>1回目のWaitForSingleObjectから戻った時点では非シグナル状態、ということになりま
す
いえ、繰り返すとそうならない事が分かりました。でも、有難うございました。

皆さん、どうも有難うございました。

おもち 2008/02/19(火) 14:06:14
言い忘れておりました。Sleep(1)は削除して実験しました。

シャノン 2008/02/19(火) 14:35:03
> ・まず数回WAIT_TIMEOUT。表示回数は実行毎に変動
> ・直後に1回だけWAIT_OBJECT_0。
> ・その後はずっとWAIT_TIMEOUT。

どうして、この結果から、

> WaitForSingleObject( ???, 0 )は、非シグナル化(リセット)しない

という結論が出るのかわからないんですが。

WaitForSingleObject( handle, 0 ) がタイマをリセットしないなら、自動リセットタイ
マであってもリセットされない=手動リセットと同じ、一度シグナル状態になったら、
SetWaitableTimerしない限りずーっとシグナル状態、であるはずです。
ならば、一旦 WAIT_OBJECT_0 になったあとは、ずーっと WAIT_OBJECT_0 でないといけな
いでしょう。
WAIT_OBJECT_0 が一度だけということは、待ち時間が 0 であってもリセットされている
ことの証拠なのでは?

おもち 2008/02/19(火) 19:22:41
>WAIT_OBJECT_0 が一度だけということは、待ち時間が 0 であってもリセットされている
ことの証拠なのでは?

確かに言われてみればそうですね。
#何で納得していたんだろう...?頭を冷やします...
前言は撤回で、「待ち時間0でもリセット機能を有する」というのが正しそうですね。

どうも有難うございました。

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