C++11以降だとstd::mutexとstd::lock_guardがありますし、これらは簡単なクラスだから古いC++でも数秒で自作できますし、でも排他スコープが明確なJava/C#のsynchronizedの記法がうらやましいなーとこんなマクロ書いちゃうこと多いですよね。(よね?)
#define synchronized(monitor) \
if (auto __lock = std::make_unique<std::lock_guard<std::mutex>>(monitor))
こういうの定義しておくと
std::vector<int> data_; // いろんなスレッドから読み書きするデータ
std::mutex monitor_; // mutexオブジェクトを宣言しておいて
...
synchronized (motinor_) {
// 排他制御された処理
data_.doSomething();
}
Javaやあっ。
さてここからはJavaを超えに行きます。
プログラマの意図は**「data_を自スレッドしか触っていないことを保証したい」**であって、monitor_という存在は意図よりも低レベル、ノイズです。Javaだとdata_そのものにモニタの役割もさせてしまう(synchronized(data_)と書く)こともまあできますが、これはあまりよろしくない技法だから普通はmonitor_を別に用意するものです。
C++ならそれもマクロに用意させてプログラマの目から隠せる。
// 先ほどのsynchronizedの定義に追加します。
// モニタ変数の名前は _mutex_【対象変数名】 だ
#define MONITOR_OF(var) _mutex_ ## var
// 変数宣言とそれ専用のモニタ変数宣言をやってくれる
#define DECLARE_THREAD_SAFE(type, var) \
type var; \
std::mutex MONITOR_OF(var);
// 独占使用したい変数を指定する記法
#define exclusive(var) synchronized(MONITOR_OF(var))
こうすると、data_の独占使用はこうなります。
DECLARE_THREAD_SAFE(std::vector<int>, data_) // いろんなスレッドから読み書きするデータ
...
exclusive (data_) {
// 排他制御された処理
data_.doSomething();
}
synchronizedマクロですが、if構文の枠に乗せるためにmake_uniqueしてるのがなんか迂遠で汚らしいですね。なんかいい書き方ありますかね。ifでなくfor使うとか?