cppBuilder
mutex
trap

C++ Builder XE4, 10.2 Tokyo > TMutex > { ロックされない例 | ロックされる例 } | TCriticalSection > 300msecの待ちではロックされる

動作環境
C++ Builder XE4
RAD Studio 10.2 Tokyo Update 2 (追記: 2018/01/05)

TMutexを試した。

注意 (下記のコードは

Case 1. ロックがかからない

Unit1.cpp
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------

String MutexName = L"Project1";
TMutex *myMutex;
HWND HWNDMutex;

__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
    myMutex = new TMutex(false);
}

void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
    delete myMutex;
    myMutex = NULL;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    myMutex->Acquire();

    String msg1 = L"Start:" + Now().DateTimeString();
    Memo1->Lines->Add(msg1);

    for(int loop=0; loop < 50; loop++) {
        Application->ProcessMessages();
        Sleep(100); // msec;
    }
    myMutex->Release();

    String msg2 = L"End:" + Now().DateTimeString();
    Memo1->Lines->Add(msg2);
}
//---------------------------------------------------------------------------

Button1を連打した結果が以下。

結果(Memo1)
Start:2017/11/08 17:16:18
Start:2017/11/08 17:16:18
Start:2017/11/08 17:16:19
End:2017/11/08 17:16:24
End:2017/11/08 17:16:29
End:2017/11/08 17:16:33

Startのメッセージ表示は2秒内に3つ処理されている(ロックがかかっていない)。
Endのメッセージ表示は5秒弱間隔になっている(ロックがかかっている)。

Case 2. ロックがかかる例

Acquire()の後に200msecほど「待ち」を入れるときちんとロックされるようだ。
(100msecの待ちではロックされなかった)。

Unit1.cpp
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------

String MutexName = L"Project1";
TMutex *myMutex;
HWND HWNDMutex;

__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
    myMutex = new TMutex(false);
}

void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
    delete myMutex;
    myMutex = NULL;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    myMutex->Acquire();

    for(int loop=0; loop < 20; loop++) {
        Application->ProcessMessages();
        Sleep(10); // msec;
    }

    String msg1 = L"Start:" + Now().DateTimeString();
    Memo1->Lines->Add(msg1);

    //Update();
    for(int loop=0; loop < 50; loop++) {
        Application->ProcessMessages();
        Sleep(100); // msec;
    }
    myMutex->Release();

    String msg2 = L"End:" + Now().DateTimeString();
    Memo1->Lines->Add(msg2);
}
//---------------------------------------------------------------------------
結果(Memo1)
Start:2017/11/08 17:25:35
End:2017/11/08 17:25:40
Start:2017/11/08 17:25:40
End:2017/11/08 17:25:45
Start:2017/11/08 17:25:45
End:2017/11/08 17:25:50

Case 3. TCriticalSection

TMutexの代わりにTCriticalSectionを試した。

Case2と同様の200msecの「待ち」ではロックがうまく動作しなかった。
300msecの「待ち」ではロックがかかった。

Case 4. Boost::scoped_lock

下記の場合は、Case2と同様に200msecの「待ち」を必要とした。

boost::mutex::scoped_lock(s_mutex);