早速で恐縮ですが、下のコード時、
「最下行の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なので、シグナル状態の検査のみを行う機能になっている。
従ってシグナル化待機と自動リセット(非シグナル化)はされない」
と考えた為です。
が、同僚は「リセット状態」という意見でした。
テストプログラムでもよく分からなかった為、皆様に意見を伺った次第です。
どうぞ宜しくお願い致します。
環境の記載を忘れておりました。
WinXP Pro. + 最新パッチ、VC++8
失礼しました。
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じゃないのかな。
秒のケタ間違えてた
びみょ~な単位時間でのタイマーの扱いは不慣れなので、ちょい不安ですが。
> HANDLE h( CreateWaitableTimer( NULL, FALSE, " ) );
最後の"って大丈夫でしょうか? 空文字の場合はNULL指定の場合の名前なしと
別の扱いを受ける気がします。(結果に対しての影響はないハズですが)
> DueTime.QuadPart = -1LL; // 100ns後に即シグナル化
-1Lの誤記、カナ?
> Sleep( 1 ); // 1ms待機.故に,タイマはシグナル状態
コメントに書いてあるように、このステートメントが完了した時点でシグナルな
はずなので、WaitForSingleObject()はWAIT_OBJECT_0が返るのでは、と予測
します。
> テストプログラムでもよく分からなかった為
よく分からなかった、とはどゆ意味でしょうか?
# 100ns, 1msのような短時間での検証の必要性はあるのでしょうか?
# 特にそのようにする必要がないように思われます。
>> DueTime.QuadPart = -1LL; // 100ns後に即シグナル化
> -1Lの誤記、カナ?
LONGLONGの時って、LLと書けたのですね。初めて知りました m(__)m
「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かどうか調べるだけでいいと思います。
やってみりゃーいいじゃないのー。
以下のように修正して実行。
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から戻った時点では非シグナル状態、ということに
なります。
…これじゃダメなの?
とりあえず、
> テストプログラムでもよく分からなかった為、皆様に意見を伺った次第です。
> どうぞ宜しくお願い致します。
シャノンさんが提示されているような方法でわかるはずなのに
なぜ解らなかったのかの方が興味あります。
ぜひ説明をお願いします。
結論は「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から戻った時点では非シグナル状態、ということになりま
す
いえ、繰り返すとそうならない事が分かりました。でも、有難うございました。
皆さん、どうも有難うございました。
言い忘れておりました。Sleep(1)は削除して実験しました。
> ・まず数回WAIT_TIMEOUT。表示回数は実行毎に変動
> ・直後に1回だけWAIT_OBJECT_0。
> ・その後はずっとWAIT_TIMEOUT。
どうして、この結果から、
> WaitForSingleObject( ???, 0 )は、非シグナル化(リセット)しない
という結論が出るのかわからないんですが。
WaitForSingleObject( handle, 0 ) がタイマをリセットしないなら、自動リセットタイ
マであってもリセットされない=手動リセットと同じ、一度シグナル状態になったら、
SetWaitableTimerしない限りずーっとシグナル状態、であるはずです。
ならば、一旦 WAIT_OBJECT_0 になったあとは、ずーっと WAIT_OBJECT_0 でないといけな
いでしょう。
WAIT_OBJECT_0 が一度だけということは、待ち時間が 0 であってもリセットされている
ことの証拠なのでは?
>WAIT_OBJECT_0 が一度だけということは、待ち時間が 0 であってもリセットされている
ことの証拠なのでは?
確かに言われてみればそうですね。
#何で納得していたんだろう...?頭を冷やします...
前言は撤回で、「待ち時間0でもリセット機能を有する」というのが正しそうですね。
どうも有難うございました。