////////////////////////////////////////////////////////////////////
/*

    KAB-studio.h


    (C)KAB-studio 1999 - 2004 ALL RIGHTS RESERVED.
        http://www.kab-studio.biz/
        info@mail.kab-studio.biz

    送信日： 2004/12/20(Mon) No.287
    配信数： 2036
    発行元： まぐまぐ ( URL: http://www.mag2.com/  ID: 0000012198 )
*/
////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////
/*                ２００４年１２月２０日（月）の更新              */
http://www.kab-studio.biz/index.html

・ほとはー外伝３、仮スタート
　三人合体ホットハーブの外伝３、【ワタシのキロク】のプレページを作り
ました。まだ中身はないですし、本連載も来月からなのでしばしお待ち
を……。
[ 三人合体ホットハーブ 外伝３ ワタシのキロク ]
http://www.kab-studio.biz/Comic/HotHerbA3/index.html


////////////////////////////////////////////////////////////////////
/*                        ちょお普通な日記                        */
http://www.kab-studio.biz/nikki2/index.html

2004/12/12 (Sun)
　午前中は洗濯して電撃ももえサイズを買ったり服買ったり。４時まで
ぐだーっと。中間派遣Ｂ社に泣きついてみる。トップからの陥落。Machician
のイラスト。そして相互理解。

2004/12/13 (Mon)
　全く寝付けず、でも寝覚めスッキリ、しっかり休むっていいことなんだな
……と思ったら熱が（汗）。レビューは結局関係なく？　風邪に感謝。そし
てわがまま。

2004/12/14 (Tue)
　実家とクリスマスな一日。銀座久兵衛と三笠會舘。専門学校の先生に、
許可降りた。そして咳止め薬。そして転職情報サイト。そしてストレス。

2004/12/15 (Wed)
　ドキュメントのまとめとか詳細設計書起こしとか。派遣先Ｃ社の人に
プロパーとしてのポジションを求められる。 NHK インタビューを受ける。
そして起きられない。

2004/12/16 (Thu)
　おしごとは詳細設計書起こし。グランドマンボウソファーは寝るのに向い
てない？　KURAU 最終回はあんま……。今年を振り返る！　１月は前々プロ
ジェクトで忙しい。そして契約範囲内の仕事。そして年齢なりの仕事。

2004/12/17 (Fri)
　今日も詳細設計書起こし。月曜は１０階プロジェクトに。舞-HIMEがかな
り気合い入ってた。今年を振り返る。２月は Fate 三昧。そして mixi 。

2004/12/18 (Sat)
　朝からおでかけ。戸部駅・カレーのバーグでハンバーグカレーを。メロン
ブックスでコミックスを、丸井でスーツを、ヨドバシでハードディスクを購
入。帰ってからはのんびりしてハードディスク入れて。今年を振り返る。
３月４月は Remember11 。そしてバンダイビジュアル。


////////////////////////////////////////////////////////////////////
/*                         風雅、舞い                             */
http://www.kab-studio.biz/Novel/Fuga/index.html

■　第十一章　ファインダウト社　−１４−

　一歩後ろに下がって、観戦スタイルを観察する。その姿は、三者三様。
　美咲は冷静に分析しつつも、自らの子の成長ぶりに少なからず驚いてい
る。
　俊雄は手を握り、ただひたすら恐怖と不安に耐え、舞の心配をし続けてい
る。
　恭子は両腕を振り上げ、届かんばかりの歓声を大声で張り上げていた。
　智子はふたりの戦いそのものには興味がない。むしろ、各種センサーが捉
えている観測データの方が興味深かった。モニターに表示される無数の折れ
線グラフ。舞と少年のデータは似た箇所もあれば全く異なる箇所もある。
　漠然と、少年達ＡＰと、泉の能力者は同じ性質を持つのでは、というイ
メージを描いていた。
　しかし、客観的な記録はその多くを否定する。
　科学者としての智子は、ＡＰの戦闘能力やその結果には興味がない。ＡＰ
の組成、性質、成長過程に興味があった。
　だから、模擬訓練そのものには興味がない。
「よしっ！！」
　恭子がガッツポーズを取る。水槍が少年に当たり、水飛沫が飛ぶ。恭子が
喜ぶほどのダメージは負っていないが、少年が距離を詰めることに苦労して
いるようには見えた。
　けたたましいブザー。
「はい、１分間休憩、その後最終ラウンドです」
『はい』
　元気な舞の声が白い空間に反響する。壁の端まで来て腰を下ろす舞に対し
て、少年は少し壁寄りに移動しただけでそのまま立っていた。
「舞さん、疲れてるみたいですね」
「それは大丈夫だと思うわ、さっきも試合前には回復していた」
　舞から目を離さずに美咲が答える。
「肉体的なダメージを負っていないとはいえ、なぜあれほどの回復力がある
のでしょうか」
「恐らく泉そのものの影響なんだと思うけど……」
　それでも、美咲自身が体験したことのないことは、説明できない。
　元気よく舞が立ち上がり、少年の方へと歩いていく。手に拳を打ち当て
て、
『よっしゃー！』
　などという元気な声が上がる。
「……」
　その舞へと向ける少年の視線は、殺意を持っていた。
                                                              (続く)


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~[KCM]
Machician 第４話……鋭意制作中。再開は来年１月３日から！
[ Machician ]
http://d.hatena.ne.jp/kab_studio/20040823#1093276416
[ Machician＋設定 最新一覧 ]
http://d.hatena.ne.jp/kab_studio/searchdiary?word=*%5BMachician
_______________________________________________________________[KCM]

////////////////////////////////////////////////////////////////////
/*                       #pragma twice                            */
http://www.kab-studio.biz/Programing/PragmaTwice/index.html

　Version 14.20
クリティカルセクションと同期オブジェクト

「今回は、さらにクリティカルセクションをの使い方について見てみます」
『へー、他の同期オブジェクトなんて２回ずつしかやらなかったのに』
「それだけクリティカルセクションは使いやすいし、使う場面も多いから
ね。それに、使うのが難しいっていうのもあるかな」
『難しい？』
「まず、前回の例を思い出して。前回は g_iData という変数を各スレッド
で共通で使用していたから、この変数にアクセスする箇所を排他するために
クリティカルセクションを使用しました」
『読み込んで、書き込むところを囲んだわけよね』
「ということは、同じく g_iData にアクセスする箇所があった場合、同じ
ように囲まなきゃいけないってことです」
『？』
「たとえば」

// 別スレッドで呼び出される、 g_iData を増やし続ける関数。
void __cdecl IncrementThreadOld( void *p_p )
{
    TRACE( "スレッド開始。\n" );
    for( int iF1 = 0; iF1 < 10; ++iF1 )
    {
        int i = g_iData;
        // 0.1 秒待ちます。
        Sleep( 100 );
        g_iData = i + 1;
        TRACE( "%d\n", g_iData );
    }
    TRACE( "スレッド終了。\n" );
}

『あれ、クリティカルセクション使ってない、ってゆーか前のだね』
「これを混在させたら？」

    HANDLE hThreadAry[3];
    hThreadAry[0]
        = (HANDLE)_beginthread( IncrementThread, 0, NULL );

    hThreadAry[1]
        = (HANDLE)_beginthread( IncrementThread, 0, NULL );

    hThreadAry[2]
        = (HANDLE)_beginthread( IncrementThreadOld, 0, NULL );

『え”、それって意味ないんじゃない？』
「そう、意味がないんです。 g_iData にアクセスする箇所はすべて同期を
取らないと意味がないんです。でも……」
『でも？』
「 g_iData はグローバル変数なので、色々な関数からアクセスできます。
もしプログラムが大きくて、色々な関数から g_iData にアクセスしていたら
……」
『……全部クリティカルセクションで囲まなきゃいけないってこと？　うわ
めんどくさー』
「そういうこと。たとえばこんな感じに」

// 別スレッドで呼び出される、 g_iData を増やし続ける関数。
void __cdecl IncrementThreadOld( void *p_p )
{
    TRACE( "スレッド開始。\n" );
    for( int iF1 = 0; iF1 < 10; ++iF1 )
    {
        // クリティカルセクションでロックを掛けます。
        EnterCriticalSection( &g_stCriticalSection );

        int i = g_iData;
        // 0.1 秒待ちます。
        Sleep( 100 );
        g_iData = i + 1;
        TRACE( "%d\n", g_iData );

        // クリティカルセクションのロックを解除します。
        LeaveCriticalSection( &g_stCriticalSection );
    }
    TRACE( "スレッド終了。\n" );
}

『なるほど、同じように囲めばいいわけね』
「同期オブジェクト、つまり同じ g_stCriticalSection を使えば、両方と
も同期を取ってくれるから」
『？』
「えっと、たぶん感覚的にはわかってるんだろうけど……この例を試してみ
て」

// 共有する変数。
int g_iData = 0;

// クリティカルセクション用同期オブジェクト。
CRITICAL_SECTION g_stCriticalSection;

// クリティカルセクション用同期オブジェクト（Old用）。
CRITICAL_SECTION g_stCriticalSectionOld;

// 別スレッドで呼び出される、 g_iData を増やし続ける関数。
void __cdecl IncrementThread( void *p_p )
{
    TRACE( "スレッド開始。\n" );
    for( int iF1 = 0; iF1 < 10; ++iF1 )
    {
        // クリティカルセクションでロックを掛けます。
        EnterCriticalSection( &g_stCriticalSection );

        int i = g_iData;
        // 0.1 秒待ちます。
        Sleep( 100 );
        g_iData = i + 1;
        TRACE( "%d\n", g_iData );

        // クリティカルセクションのロックを解除します。
        LeaveCriticalSection( &g_stCriticalSection );
    }
    TRACE( "スレッド終了。\n" );
}

// 別スレッドで呼び出される、 g_iData を増やし続ける関数。
void __cdecl IncrementThreadOld( void *p_p )
{
    TRACE( "スレッド開始。\n" );
    for( int iF1 = 0; iF1 < 10; ++iF1 )
    {
        // クリティカルセクションでロックを掛けます。
        EnterCriticalSection( &g_stCriticalSectionOld );

        int i = g_iData;
        // 0.1 秒待ちます。
        Sleep( 100 );
        g_iData = i + 1;
        TRACE( "%d\n", g_iData );

        // クリティカルセクションのロックを解除します。
        LeaveCriticalSection( &g_stCriticalSectionOld );
    }
    TRACE( "スレッド終了。\n" );
}


// IncrementThread() を別スレッドとして呼び出す関数。
// この関数をボタンのイベントハンドラとかで呼んでください。
void CallThread()
{
    // クリティカルセクションを初期化します。
    InitializeCriticalSection( &g_stCriticalSection );
    InitializeCriticalSection( &g_stCriticalSectionOld );

    HANDLE hThreadAry[3];
    hThreadAry[0]
        = (HANDLE)_beginthread( IncrementThread, 0, NULL );

    hThreadAry[1]
        = (HANDLE)_beginthread( IncrementThread, 0, NULL );

    hThreadAry[2]
        = (HANDLE)_beginthread( IncrementThreadOld, 0, NULL );

    WaitForMultipleObjects( 3, hThreadAry, TRUE, 100 * 1000 );

    TRACE( "処理完了。\n" );
    TRACE( "%d\n", g_iData );

    // クリティカルセクションを削除します。
    DeleteCriticalSection( &g_stCriticalSection );
    DeleteCriticalSection( &g_stCriticalSectionOld );
}

『クリティカルセクションの同期オブジェクトがふたつある』
「 IncrementThread() と IncrementThreadOld() 用、別々に用意しまし
た。すると……」
『あれ？　結果が 20 になっちゃった』
「これは、 IncrementThread() と IncrementThreadOld() が別々に同期を
取っているから。たとえば」

void __cdecl IncrementThread( void *p_p )
{
...
        // クリティカルセクションでロックを掛けます。
        EnterCriticalSection( &g_stCriticalSection );
// ※↓スレッド１進行中↓
// g_stCriticalSection にロックがかかりました。

「 IncrementThread() がロックを掛けている状態の時、」

void __cdecl IncrementThreadOld( void *p_p )
{
...
// ※↓スレッド２進行中↓
        // クリティカルセクションでロックを掛けます。
        EnterCriticalSection( &g_stCriticalSectionOld );

「このとき、 g_stCriticalSectionOld は g_stCriticalSection と全く関
係がないので、 g_stCriticalSection にセットされている〈ロック中〉情
報がありません」
『ってことは……』
「排他されずに」

void __cdecl IncrementThreadOld( void *p_p )
{
...
        // クリティカルセクションでロックを掛けます。
        EnterCriticalSection( &g_stCriticalSectionOld );
// ※↓スレッド２進行中↓
// g_stCriticalSectionOld にロックがかかりました。

『げ、これじゃ意味ないじゃん』
「対して、同じ変数を使っていた場合」

// ※↓スレッド２進行中↓
// ロックがかかっているので待機します。
        // クリティカルセクションでロックを掛けます。
        EnterCriticalSection( &g_stCriticalSection );

「同じ g_stCriticalSection を参照すれば、スレッド１が掛けたロックを
スレッド２もちゃんと見てくれます」
『これなら関数が増えても問題なしってわけね』
「それはそうなんだけど、 g_iData にアクセスする箇所がどんどん増えて
いったら？」
『う”』
「そのうえ、 g_iData から取得するところと g_iData に書き込むところが
別々になったりしたら」
『うわ……考えたくないし、そういうプログラム作らなきゃいいんで
しょ？』
「それができたらねぇ……」

/*
    Preview Next Story!
*/
『なんかちゃんと同期を取るのって大変そう』
「マルチスレッドが難しい理由のひとつだね」
『しかも複雑になればなるほど……』
「しかも、クリティカルセクションでもデッドロックが発生します」
『げ』
「というわけで次回」
＜ Version 14.21 スレッドでデッドロック ＞
『につづく！』
「クリティカルセクションもちゃんとした同期オブジェクトってことで」
『デッドロックが起こせることが〈ちゃんと〉なの？』


////////////////////////////////////////////////////////////////////
/*                ２００４年１２月２７日（月）の更新              */
http://www.kab-studio.biz/index.html

・ほとはー外伝３のページを充実予定？
　まだプレページ状態のほとはー外伝３のページをもう少し充実させる予
定。


////////////////////////////////////////////////////////////////////
/*                          ご注意！！                            */

・このメールを返信しないでください。
・ご意見・ご希望・ご感想は[チョー普通な日記]よりお送りください。
http://www.kab-studio.biz/nikki2/
・購読登録を解除したいときにはこのページで行なってください。
http://www.mag2.com/m/0000012198.htm
・解除は自分で行なってください。
・バックナンバーはこれらのページにあります。
http://backno.mag2.com/reader/Back?id=0000012198
http://www.kab-studio.biz/Freeware/index.html#MailMagazine


////////////////////////////////////////////////////////////////////
/*
    KAB-studio.h
      Weekly Mail Magazine.
      Written by Kaburaya Seiden.
      http://www.kab-studio.biz/Info/MailMagazine/

    (C)KAB-studio 1999 - 2004 ALL RIGHTS RESERVED.
        http://www.kab-studio.biz/
        info@mail.kab-studio.biz
*/
////////////////////////////////////////////////////////////////////

