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

    KAB-studio.h


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

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

/*                         来週はお休み                           */

　来週、１月３日分の配信はお休みします。
　年末年始ということで。

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

・ごめんお休み
　今週の更新は特にないです。ごめんなさい……。


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

2004/12/19 (Sun)
　似顔絵とほとはー外伝３。白黒難しい。１月表紙壁紙どうしよう。
モンキーターンＶ最終回。NHKに言いたい。今年を振り返る、５月６月。忙
しい中、 CLANNAD と上海旅行。そしてパト２。そして内臓と内蔵。そして
スーツ。

2004/12/20 (Mon)
　１０階と１７階。仕事枯渇が問題だった？　今年を振り返る、７月。5.1ch
とひとりぼっち。そしてセルシェーディング。そして mixi 。

2004/12/21 (Tue)
　仕事で徹夜。１０階プロジェクトで Java をがーっと。急遽１７階に戻さ
れてあっという間に午前５時。始発＋１で帰宅。

2004/12/22 (Wed)
　昨日は徹夜。突発的な徹夜は初めて。ラッキーだった。このプロジェクト
は本当に大きいらしい。明日は休出。今年を振り返る、８月。仕事の合間に
京都旅行とか。仕事して忘れる。そして忘年会６０人。

2004/12/23 (Thu)
　１０時から休出。１０階と１７階で０時上がり。胃がキリキリいってほと
んど何も食べられなかった……。今年を振り返る、９月。天国だった頃。そ
して派遣の契約。そして1人月200万円。

2004/12/24 (Fri)
　納期で微妙に忙しい。今週は辛かった……。土日ちゃんと休めます。
今年を振り返る、１０月。東京駅近く勤務。そしてクリスマス。

2004/12/25 (Sat)
　徹ゲーに行ってきます。プラネテスとかアイアンリーガーとかが届いて起
きる。午後はプラネテスをゆっくり見つつかぶヘッダーの準備とか。種死の
モビルアーマーが……。今年を振り返る、１１月。３プロジェクト同時。


////////////////////////////////////////////////////////////////////
/*                         風雅、舞い                             */
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.21
スレッドでデッドロック

「今回は、以前紹介したデッドロックについて」
『 Version 14.07 ( No.274 ) のだよね。あのときと何が違うの？』
「この前はミューテックスで試したけど、今回はクリティカルセクションで
デッドロックしてみます」
『あー、そういうことね』

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

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

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

        TRACE( "IncrementThread1() 1 と 2 の間。\n" );
        // 0.1 秒待ちます。
        Sleep( 100 );

        EnterCriticalSection( &g_stCriticalSection2 );

        TRACE( "IncrementThread1() 2 の後。\n" );

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

// 別スレッドで呼び出される、 g_iData を増やし続ける関数。
void __cdecl IncrementThread2( void *p_p )
{
    TRACE( "スレッド開始。\n" );
    for( int iF1 = 0; iF1 < 10; ++iF1 )
    {
        EnterCriticalSection( &g_stCriticalSection2 );

        TRACE( "IncrementThread2() 2 と 1 の間。\n" );
        // 0.1 秒待ちます。
        Sleep( 100 );

        // クリティカルセクションでロックを掛けます。
        EnterCriticalSection( &g_stCriticalSection1 );

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


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

    HANDLE hThreadAry[2];
    hThreadAry[0]
        = (HANDLE)_beginthread( IncrementThread1, 0, NULL );
    hThreadAry[1]
        = (HANDLE)_beginthread( IncrementThread2, 0, NULL );

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

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

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

『クリティカルセクションがふたつ……そういえば、ミューテックスの時も
そうだったね』
「基本的にデッドロックが起きるのは同期オブジェクトが複数ある場合。
デッドロックする仕組みは……」

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

        TRACE( "IncrementThread1() 1 と 2 の間。\n" );
        // 0.1 秒待ちます。
        Sleep( 100 );

        EnterCriticalSection( &g_stCriticalSection2 );

「と」

// 別スレッドで呼び出される、 g_iData を増やし続ける関数。
void __cdecl IncrementThread2( void *p_p )
{
    TRACE( "スレッド開始。\n" );
    for( int iF1 = 0; iF1 < 10; ++iF1 )
    {
        EnterCriticalSection( &g_stCriticalSection2 );

        TRACE( "IncrementThread2() 2 と 1 の間。\n" );
        // 0.1 秒待ちます。
        Sleep( 100 );

        // クリティカルセクションでロックを掛けます。
        EnterCriticalSection( &g_stCriticalSection1 );

「で、使用しているクリティカルセクションが逆になってるでしょ。これが
ポイント」
『 IncrementThread1() は 1 → 2 の順、 IncrementThread2() は 2 → 1 
の順なんだね』
「この順でロックを掛けると……」

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

        TRACE( "IncrementThread1() 1 と 2 の間。\n" );
        // 0.1 秒待ちます。
// スレッド１がここで 0.1 秒待っている間に……
        Sleep( 100 );

        EnterCriticalSection( &g_stCriticalSection2 );

「このように、スレッド１が Sleep() で 1 と 2 の間で待っている間に」

// 別スレッドで呼び出される、 g_iData を増やし続ける関数。
void __cdecl IncrementThread2( void *p_p )
{
    TRACE( "スレッド開始。\n" );
    for( int iF1 = 0; iF1 < 10; ++iF1 )
    {
        EnterCriticalSection( &g_stCriticalSection2 );

        TRACE( "IncrementThread2() 2 と 1 の間。\n" );
        // 0.1 秒待ちます。
// スレッド２もここで待っていると……
        Sleep( 100 );

        // クリティカルセクションでロックを掛けます。
        EnterCriticalSection( &g_stCriticalSection1 );

「スレッド２が入ってきちゃうと、スレッド１が……」

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

        TRACE( "IncrementThread1() 1 と 2 の間。\n" );
        // 0.1 秒待ちます。
        Sleep( 100 );

// スレッド１がここでロック解除待ち。
        EnterCriticalSection( &g_stCriticalSection2 );

「と、スレッド２が掛けたロックが解けるのを待つことになります」
『で、スレッド２も……』

// 別スレッドで呼び出される、 g_iData を増やし続ける関数。
void __cdecl IncrementThread2( void *p_p )
{
    TRACE( "スレッド開始。\n" );
    for( int iF1 = 0; iF1 < 10; ++iF1 )
    {
        EnterCriticalSection( &g_stCriticalSection2 );

        TRACE( "IncrementThread2() 2 と 1 の間。\n" );
        // 0.1 秒待ちます。
        Sleep( 100 );

// スレッド２がここでロック解除待ち。
        // クリティカルセクションでロックを掛けます。
        EnterCriticalSection( &g_stCriticalSection1 );

『スレッド１が掛けたロックが解けるのを待っちゃう、でもスレッド１も
待ってるわけだから』
「どうしようもなくなっちゃいます」
『げ』
「しかも WaitForSingleObject() と違ってタイムアウトしないから」
『……永久？』
「というわけで、このプログラムは強制終了してください」

/*
    Preview Next Story!
*/
『ホントに簡単にデッドロックしちゃうね』
「ふたつ同期オブジェクトがあると簡単になっちゃうから」
『……あ！』
「はい火美ちゃん」
『いいアイディア思いついたんだけど！』
「というわけで次回」
＜ Version 14.22 複数の同期オブジェクト ＞
『につづく！』
「次回はそのアイディアの問題点についても」
『ってまだ言ってねー！！』


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

・１月表紙壁紙！
　やっぱりお正月でしょう、ということで新しい表紙壁紙の予定。
　さて、ほとはーにするか、Machicianにするか……。


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

・KAB-studio.h お休み
　年末年始恒例ということで KAB-studio.h のこの週の号はお休みとなりま
す。御了承ください。
　この週の他の更新もない予定。申し訳ないです……。


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

・このメールを返信しないでください。
・ご意見・ご希望・ご感想は[チョー普通な日記]よりお送りください。
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
*/
////////////////////////////////////////////////////////////////////

