#C++/CLIとC++混在でstd::mutex使えない
C++/CLIが呼び出しているC++の関数内で排他制御したいがstd::mutex使うと
VS2017ではビルド時に「 is not supported when compiling with /clr or /clr:pure」というエラーになる。
C++/CLIだけならば代わりにmsclr\lock.hが使えるがC++では使えない。
ついでに、調べるとWLRとかいうのでも使えそうなものが試すとこれもエラーに。
C++/CLIが呼び出しているC++内で排他制御するにはwinAPIを使うしかないっぽい。
以下を使う。
#include<windows.h>
//初期化 コンストラクタなどで
HANDLE hMutex = CreateMutex(NULL,FALSE,NULL);
//ロック取得
WaitForSingleObject(hMutex, INFINITE);
//なんか排他的に実行したい処理
//ロック解放
ReleaseMutex(hMutex);
//終了 デストラクタなどで
CloseHandle(hMutex);
しかし、これを素直に使うとロック解放忘れ、クローズし忘れでバグ作りそうなので、std::lock_guardのようにロック取得したブロック(lock_guardのインスタンスのスコープ)を抜けると勝手にロック解放されるようにしたい。
ネット探すと無駄に高機能な実装みたいなのが見つかった気がするけど、そんな大した機能はいらないのでMutex限定で超簡単な実装を作ってみた。
#std::mutex、std::lock_guardの代わりの実装
ヘッダーオンリーです。
どうぞご自由に改変、ご使用ください。
ソースはhidetaka0/VCppMutexにも上げています。
#pragma once
#include <windows.h>
class Mutex
{
private:
HANDLE g_hMutex;
public:
Mutex()
{
//Mutex生成
g_hMutex = CreateMutex(NULL, FALSE, NULL);
}
~Mutex()
{
//クローズ
CloseHandle(g_hMutex);
}
//ロック
void Lock()
{
WaitForSingleObject(g_hMutex, INFINITE);
}
//アンロック
void Unlock()
{
ReleaseMutex(g_hMutex);
}
};
class MutexLockGuard
{
private:
Mutex * g_Mutex;
public:
MutexLockGuard(Mutex * mutex)
{
g_Mutex = mutex;
g_Mutex->Lock();//ロック
}
~MutexLockGuard()
{
g_Mutex->Unlock();//アンロック
}
};
#使い方
①Mutexクラスのインスタンス作成
②ロックしたいブロックでMutexLockGuardのコンストラクタに①のインスタンスのアドレス与えてインスタンスを生成する。
#pragma once
#include "Mutex.h"
class MutexTest
{
public:
MutexTest();
~MutexTest();
public:
//Mutexクラスのインスタンス
Mutex MyMutex;
//テスト用数
void TestRun()
{
//ロック取得
{
MutexLockGuard lock(&MyMutex);//ブロックを抜けると勝手にアンロック
//なんか排他的に実行したい処理
//・・・
}
};
};