#pragma twice

KAB-studio > プログラミング > #pragma twice > 277 Version 14.10 タイマーを使おう!

#pragma twice 277 Version 14.10 タイマーを使おう!

前のページへ 表紙・目次へ 次のページへ

 Version 14.10
タイマーを使おう!

同期オブジェクト3つめはタイマーです

タイマー ( Waitable timer )

タイマーも仕組みそのものは難しくありません
バトンとかそんな感じ?
そういうこと。同じように走ることを例に取ると

・一定時間毎に走り出す

のがタイマーかな

選手A、B、Cがいる時に、まずAが走って、その1分後にBが走って、
そのさらに1分後にCが走る
ハンデみたいな感じ?
そんな感じ。まずはいつも通り、プログラムを見てもらおうか

namespace B1
{

HANDLE g_hTimer = NULL;
const char *const TIMER_NAME= "ProcessesTimer";

// タイマーを作成します。
void Create()
{
    g_hTimer = CreateWaitableTimer( NULL, FALSE, TIMER_NAME );
    TRACE( "%x\n", g_hTimer );
}

// タイマーを取得します。
void Open()
{
    g_hTimer = OpenWaitableTimer( TIMER_ALL_ACCESS, FALSE, TIMER_NAME );
    TRACE( "%x\n", g_hTimer );
}

// タイマーをセットします。
void Set()
{
    // タイマーを開始するまでの100ナノ秒数。
    const int DUE_NSEC = -5 * 1000 * 1000 * 10;
    LARGE_INTEGER largeInteger;
    largeInteger.QuadPart = DUE_NSEC;
    // タイマーの間隔のミリ秒数。
    const int INTERVAL_MSEC = 15000;
    BOOL b 
        = SetWaitableTimer
            ( g_hTimer
            , &largeInteger
            , INTERVAL_MSEC
            , NULL
            , NULL
            , FALSE
            );
    TRACE( "%d\n", b );
}

// タイマーを監視して待機状態に入ります。
void Wait()
{
    TRACE( "待機開始。\n" );
    DWORD dwResult = WaitForSingleObject( g_hTimer, 120000 );

    if( dwResult == WAIT_TIMEOUT )
    {
        TRACE( "タイムアウト。\n" );
    }
    else
    {
        TRACE( "待機終了。\n" );
    }
}

// タイマーをキャンセルします。
void Cancel()
{
    LONG lCount = 0;
    BOOL b = CancelWaitableTimer( g_hTimer );
    TRACE( "%d\n", b );
}

// タイマーを削除します。
void Close()
{
    CloseHandle( g_hTimer );
}

}

前回と関数の数と名前が違うから注意して
 Set() が追加されて…… Release() が Cancel() になってる?
そうです。このあたりはタイマーが他の同期オブジェクトと違う点かな。
じゃあ、ひとつずつ見ていこうか

HANDLE g_hTimer = NULL;
const char *const TIMER_NAME= "ProcessesTimer";

これはいつもと同じ、ハンドルと名前ね
この辺はどの同期オブジェクトも同じだから。次も同じ

// タイマーを作成します。
void Create()
{
    g_hTimer = CreateWaitableTimer( NULL, FALSE, TIMER_NAME );
    TRACE( "%x\n", g_hTimer );
}

これはタイマーを作る関数。引数も他と同じ
じゃ、次

// タイマーを取得します。
void Open()
{
    g_hTimer = OpenWaitableTimer( TIMER_ALL_ACCESS, FALSE, TIMER_NAME );
    TRACE( "%x\n", g_hTimer );
}

これも同じ、元々作ってあるタイマーを取得します
 TIMER_NAME と同じ名前のタイマーを取得するんだね
そういうこと。では次、これはちょっとややこしいです
追加された関数だね

// タイマーをセットします。
void Set()
{
    // タイマーを開始するまでの100ナノ秒数。
    const int DUE_NSEC = -5 * 1000 * 1000 * 10;
    LARGE_INTEGER largeInteger;
    largeInteger.QuadPart = DUE_NSEC;
    // タイマーの間隔のミリ秒数。
    const int INTERVAL_MSEC = 15000;
    BOOL b 
        = SetWaitableTimer
            ( g_hTimer
            , &largeInteger
            , INTERVAL_MSEC
            , NULL
            , NULL
            , FALSE
            );
    TRACE( "%d\n", b );
}

この関数は、タイマーを実際にセットします
時間セットしてオンにする、みたいな?
そういうこと。 OpenWaitableTimer() は作るだけだから、この 
SetWaitableTimer() でセットしなきゃいけないんです
でも数字多くてよくわかんない……
使う数はふたつ。まずひとつめは、タイマーが一番最初にオンになるまで
の時間

    // タイマーを開始するまでの100ナノ秒数。
    const int DUE_NSEC = -5 * 1000 * 1000 * 10;

ナノ秒……?
1秒の1000分の1がミリ秒、ミリ秒の1000分の1がマイクロ秒、
マイクロ秒の1000分の1がナノ秒。あ、この単位は100ナノ秒だか
ら、マイクロ秒の10分の1が100ナノ秒
すごく小さな数……
でもナノって数はあまり気にしなくていいかも。この例では 5 だから
5秒後ってこと
ん? マイナス付いてるけど
実はこの第2引数にはふたつの使い道があるんです

・正の数:1601/01/01 00:00:00 からののべ時間
・負の数:呼び出した瞬間からののべ秒

つまり、正の時間を使えば〈2004年1月1日0時0分0秒から〉とい
うふうにきっちりとした時間からタイマーを開始できるんです
そっちはタイマーっていうよりアラームだね
どっちの場合でも、 LARGE_INTEGER っていう構造体に入れて渡します

    LARGE_INTEGER largeInteger;
    largeInteger.QuadPart = DUE_NSEC;

この構造体は 64 ビットサイズの整数値を入れられます
 64 ビットっていうと…… int が 32 ビットだからその倍だね
 int の最大値より、 2 の 32 乗大きい数を入れられるってことだから
うわすご!
100ナノ秒だし、正の数の時には大きな数になるからね……で、今のが
スタートするまでの時間。次はタイマーの間隔

    // タイマーの間隔のミリ秒数。
    const int INTERVAL_MSEC = 15000;

タイマーは一定時間毎にオンになるから、その間隔
これはミリ秒数だから……15秒間隔だよね
そう。この例だと15秒間隔でオンになります。このタイマーは、この関
数で止めます

// タイマーをキャンセルします。
void Cancel()
{
    LONG lCount = 0;
    BOOL b = CancelWaitableTimer( g_hTimer );
    TRACE( "%d\n", b );
}

これで止めるまで止まらない?
そういうこと。というわけで次回は実際に使ってみます

/*
    Preview Next Story!
*/
タイマーって、ネットで調べてもあまり例ないよね
ちょっと使い方が難しいっていうのもあるけど……
けど?
一番の理由は、使い道がないことかな
使い道ないの?
というわけで次回
< Version 14.11 タイマーを使ってみる! >
につづく!
ないっていうか、はっきりしないって言うか……
おまえがはっきりしろ
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。