我为此推出了自己的互斥锁,因为我不想仅仅为了这个功能而向某个重量级库添加依赖项。它用于生产代码并包含在我们的单元测试中 - 如果您发现任何问题,请告诉我。
这是一个仅限 Windows 的解决方案。
使用示例:
NamedSystemMutex m{ L"MyMutex" };
std::lock_guard<NamedSystemMutex> lock{ m };
头文件名为SystemMutex.h:
#pragma once
#include <string>
#include <windows.h> // Just needed for HANDLE
// Provides a system-wide, recursive, named lock.
// This class satisfies requirements of C++11 concept "Lockable", i.e. can be (and should be) used with unique_lock etc.
class NamedSystemMutex
{
public:
explicit NamedSystemMutex(const std::wstring& name);
~NamedSystemMutex();
// Moveable, not copyable
NamedSystemMutex(const NamedSystemMutex& other) = delete;
NamedSystemMutex(NamedSystemMutex&& other) = default;
NamedSystemMutex& operator=(const NamedSystemMutex& other) = delete;
NamedSystemMutex& operator=(NamedSystemMutex&& other) = default;
void lock();
void unlock();
bool try_lock();
private:
HANDLE handle_{};
};
执行:
#include "NamedSystemMutex.h"
#include <stdexcept>
NamedSystemMutex::NamedSystemMutex(const std::wstring& name) {
handle_ = CreateMutexW(nullptr, FALSE, name.c_str());
if (handle_ == NULL) {
throw std::runtime_error("Creation of mutex failed");
}
}
NamedSystemMutex::~NamedSystemMutex() {
const BOOL result = CloseHandle(handle_);
if (result == FALSE) {
// Error: Failed to close mutex handle (Error ignored since we are in destructor)
}
}
void NamedSystemMutex::lock() {
const auto result = WaitForSingleObject(handle_, INFINITE);
if (result == WAIT_ABANDONED) {
// Warning: Lock obtained, but on an abandoned mutex (was not correctly released before, e.g. due to a crash)
}
else if (result != WAIT_OBJECT_0) {
throw std::runtime_error("Failed to acquire lock");
}
}
void NamedSystemMutex::unlock() {
const BOOL result = ReleaseMutex(handle_);
if (result == FALSE) {
throw std::runtime_error("Failed to release lock: calling thread does not own the mutex");
}
}
bool NamedSystemMutex::try_lock() {
const auto result = WaitForSingleObject(handle_, 0);
if (result == WAIT_TIMEOUT) {
return false;
}
if (result == WAIT_OBJECT_0) {
return true;
}
throw std::runtime_error("Failed to acquire lock");
}