#pragma twice

KAB-studio > プログラミング > #pragma twice > 279 Version 14.12 イベントを使おう!

#pragma twice 279 Version 14.12 イベントを使おう!

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

 Version 14.12
イベントを使おう!

同期オブジェクト4つめはイベントです

イベント ( Event )

イベントって、催し物のイベントと同じ?
意味としては同じだけど、そこにはあまりこだわらない方がいいかも。同
期オブジェクトとしての【イベント】は、たぶん同期オブジェクトの中で一
番わかりやすくてシンプルです
今までのもそんなに複雑じゃなかったけど
でも〈バトン〉って概念は今までなかったでしょ。イベントは、簡単に言
うと〈ただのスイッチ〉
うわ簡単そう
でも、関数の数は一番多いです

HANDLE g_hEvent = NULL;
const char *const EVENT_NAME= "ProcessesEvent";

// イベントを作成します。
void Create()
{
    g_hEvent = CreateEvent( NULL, TRUE, FALSE, EVENT_NAME );
    TRACE( "%x\n", g_hEvent );
}

// イベントを取得します。
void Open()
{
    g_hEvent = OpenEvent( EVENT_ALL_ACCESS, FALSE, EVENT_NAME );
    TRACE( "%x\n", g_hEvent );
}

// イベントをセットします。
void Set()
{
    BOOL b = SetEvent( g_hEvent );
    TRACE( "%d\n", b );
}

// イベントを監視して待機状態に入ります。
void Wait()
{
    TRACE( "待機開始。\n" );
    DWORD dwResult = WaitForSingleObject( g_hEvent, 50000 );

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

// イベントをリセットします。
void Reset()
{
    BOOL b = ResetEvent( g_hEvent );
    TRACE( "%d\n", b );
}

// イベントを一瞬だけオンにします。
void Pulse()
{
    BOOL b = PulseEvent( g_hEvent );
    TRACE( "%d\n", b );
}

// イベントを削除します。
void Close()
{
    CloseHandle( g_hEvent );
}

うわ、7つもある!
関数だけ抜き出すとこんな感じ

void Create()
void Open()
void Set()
void Wait()
void Reset()
void Pulse()
void Close()

 Release() や Cancel() の代わりに…… Reset() かな?
そうだね。 Set() Reset() Pulse() がイベント独自のもの。この3つで
イベントを操作します
 Pulse() って想像つかない……
では、ひとつずつ関数を見ていきます。まずはハンドルと名前

HANDLE g_hEvent = NULL;
const char *const EVENT_NAME= "ProcessesEvent";

他のと同じ、名前で区別するのね
この辺はどの同期オブジェクトも一緒。次にイベントの作成

// イベントを作成します。
void Create()
{
    g_hEvent = CreateEvent( NULL, TRUE, FALSE, EVENT_NAME );
    TRACE( "%x\n", g_hEvent );
}

真ん中の TRUE と FALSE が謎
第2引数の TRUE は、プログラムでイベントのセットとリセットを切り替
えられるようにするためのもの。第3引数の FALSE は、最初の状態。 TRUE 
だとセット、 FALSE だとリセット
セットとかリセットとかよくわかんない
言い換えると

セット :シグナルがオンの状態
リセット:シグナルがオフの状態

ああ!
ここで重要なのは、イベントは〈シグナルの状態がずっと維持される〉と
いうことです
どゆこと?
ミューテックスを思い出して
 Version 14.06 ( No.273 ) さんしょー
ミューテックスはバトン。ミューテックスはバトンを渡した瞬間に渡した
相手だけシグナルをオンにしました
だから他の待ってるのはシグナルがオフのまま、待ち続けてたね
対して、イベントはちょっと特殊。まずリセット=シグナルがオフの場合
には、各プロセスがこのイベントを監視すると待機しつづけます
シグナルがオフなんだからそうだよね
そこで、イベントをセット=シグナルをオンにすると、待機している全て
のプロセスにシグナルオンが伝わります
ひとつだけじゃないんだ!
しかも、シグナルがオンの状態が維持されるので、このあと他のプロセス
が監視しても、シグナルがオンだからすぐに待機終了します
はー、なんかそれって、ホントの意味での信号って感じね
そうだね。セットは青、リセットは赤。イベントはそういう使い方をする
同期オブジェクトなんです
ホントに他の同期オブジェクトよりもわかりやすい……
他の同期オブジェクトは〈シグナルがひとつのプロセスにしか送られな
い〉とかのわかりづらい点があるからね。さて、話を戻すと、この例では
第3引数が FALSE なので、最初の状態はリセットになっています
シグナルがオフってことね
この状態を変更するのが次のふたつの関数

// イベントをセットします。
void Set()
{
    BOOL b = SetEvent( g_hEvent );
    TRACE( "%d\n", b );
}

// イベントをリセットします。
void Reset()
{
    BOOL b = ResetEvent( g_hEvent );
    TRACE( "%d\n", b );
}

 SetEvent() はセット=シグナルオンに、 ResetEvent() はリセット=
シグナルオフに切り替えます
これで切り替えるわけね
あともうひとつ、特別な関数があります

// イベントを一瞬だけオンにします。
void Pulse()
{
    BOOL b = PulseEvent( g_hEvent );
    TRACE( "%d\n", b );
}

この PulseEvent() は、一瞬だけセットして、すぐリセットにする関数で

スイッチをカチャカチャって切り替える感じ?
そういうこと。一瞬だけシグナルがオンになるから、待機してるすべての
プロセスはすぐに待機終了になります
で、すぐにシグナルオフに戻るから、そのあとで監視すると待機しっぱな
しってわけね
そういうこと。この関数は、とりあえず待機してるものすべてリセットし
たい場合に使います
でも SetEvent() でもいいんじゃない?
 SetEvent() はずっとシグナルオンのままだからね。たとえば待機してい
る数を数えておいて、10になったらすぐリセット、その10だけ処理をさ
せて、そのあと監視しに来たらそれは待機してもらう、で、それが10にな
るまで
ってゆーのを繰り返すわけね。並んで10人だけ入っていい、みたいな感
じ?
そういうこと。イベントはそういう使い方もできるってことで

/*
    Preview Next Story!
*/
んー
どうしたの?
他の同期オブジェクトと違うから違和感が
こっちの方がわかりやすいのに
それはそうなんだけど……
というわけで次回
< Version 14.13 イベントを使ってみる! >
につづく!
やっぱ染まってるんじゃない?
それは認めない!!
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。