LoginSignup
0
0

More than 5 years have passed since last update.

C++ Builder XE4, 10.2 Tokyo > TMutex, TCriticalSection: thread affinity | TSemaphore: not thread affinity | semaphoreでのロックコード

Last updated at Posted at 2017-11-10
動作環境
C++ Builder XE4
RAD Studio 10.2 Tokyo Update 2 (追記: 2018/01/05)

関連

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

link

上記のリンクではロックが期待通りではなかった。

stackoverflowで質問をしていたが、Remy Lebeauさんに詳細な回答をいただいた。

回答の概要
(解釈間違いがあるかもしれません

  • TMutex: thread affinityである
  • TCriticalSection: thread affinityである
  • TSemaphore: thread affinityでない
  • Thread affinityの場合、TTimerでのロックはきかない
  • これらより、TSemaphoreではTTimerのロックは可能
  • mutexはinter-thread同期として使う
  • TTimer2つではsingle threadとして動作するため、mutexはuseless
  • など

code

stackoverflowでTSemaphoreを使ったロック例を紹介いただいた。

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

#include <vcl.h>
#pragma hdrstop

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


HANDLE hSemaphore;


__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
}

__fastcall TForm1::~TForm1()
{
    if (hSemaphore)
        CloseHandle(hSemaphore);
}

void __fastcall TForm1::FormShow(TObject *Sender)
{
    hSemaphore = CreateSemaphore(NULL, 1, 1, NULL);
    if (hSemaphore == NULL) {
        OutputDebugString(L"failed to create semaphore");
    }

    Timer1->Enabled = false;
    Timer1->Interval = 1000; // msec
    Timer1->Enabled = true;

    Timer2->Enabled = false;
    Timer2->Interval =  200; // msec
    Timer2->Enabled = true;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
    if (WaitForSingleObject(hSemaphore, 0) != WAIT_OBJECT_0) {
        return;
    }

    if (CHK_update->Checked) {
        String msg = L"Timer1 " + Now().FormatString(L"yyyy/mm/dd hh:nn:ss.zzz");
        Memo1->Lines->Add(msg);
    }

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

    ReleaseSemaphore(hSemaphore, 1, NULL);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Timer2Timer(TObject *Sender)
{
    if (WaitForSingleObject(hSemaphore, 0) != WAIT_OBJECT_0) {
        return;
    }

    if (CHK_update->Checked) {
        String msg = L">>>Timer2 " + Now().FormatString(L"yyyy/mm/dd hh:nn:ss.zzz");
        Memo1->Lines->Add(msg);
    }

    ReleaseSemaphore(hSemaphore, 1, NULL);
}
//---------------------------------------------------------------------------

きちんとロックがかかった。
qiita.png

備考

mutex, critical section, semaphoreなどの機構についてはまだ学習度が浅い。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0