std::unique_ptr with RAII for mutex?



我们有很多遗留的c++ 98代码,我们正在慢慢地升级到c++11,我们有一个自定义互斥锁类的RAII实现:

class RaiiMutex
{
public:
RaiiMutex() = delete;
RaiiMutex(const RaiiMutex&) = delete;
RaiiMutex& operator= (const RaiiMutex&) = delete;
RaiiMutex(Mutex& mutex) : mMutex(mutex)
{
mMutex.Lock();
}
~RaiiMutex()
{
mMutex.Unlock();
}
private:
Mutex&  mMutex;
};

是否可以创建这个对象的std::unique_ptr ?在对象死亡时自动调用析构函数(从而解锁)仍然可以从中受益,并且还可以在非关键操作之前解锁。

示例遗留代码:

RaiiMutex raiiMutex(mutex);
if (!condition)
{
loggingfunction();
return false;
}

:后

auto raiiMutex = std::unique_ptr<RaiiMutex>(new RaiiMutex(mutex));
if (!condition)
{
raiiMutex = nullptr;
loggingfunction(); // log without locking the mutex
return false;
}

它还可以删除不必要的括号:

示例遗留代码:

Data data;
{
RaiiMutex raiiMutex(mutex);
data = mQueue.front();
mQueue.pop_front();
}
data.foo();

:后

auto raiiMutex = std::unique_ptr<RaiiMutex>(new RaiiMutex(mutex));
Data data = mQueue.front();
mQueue.pop_front();
raiiMutex = nullptr;
data.foo();

有意义吗?

编辑:由于自定义互斥类,无法使用unique_lock:

class Mutex
{
public:
Mutex();
virtual ~Mutex();
void Unlock(bool yield = false);
void Lock();
bool TryLock();
bool TimedLock(uint64 pWaitIntervalUs);
private:
sem_t mMutex;
};

Mutex中增加Mutex::lock()Mutex::unlock()Mutex::try_lock()方法。它们只是转发给Lock等方法。

则使用std::unique_lock<Mutex>

如果不能修改Mutex,请将其换行。

struct SaneMutex: Mutex {
void lock() { Lock(); }
// etc
using Mutex::Mutex;
};

SaneMutex可以随处替换Mutex

当你不能:

struct MutexRef {
void lock() { m.Lock(); }
// etc
MutexRef( Mutex& m_in ):m(m_in) {}
private:
Mutex& m;
};

包含一个适配器。

匹配c++标准的可锁要求。如果你想要定时锁定,你必须写一些胶水代码。

auto l = std::unique_lock<MutexRef>( mref );

auto l = std::unique_lock<SaneMutex>( m );

你现在有std::lock,std::unique_lock,std::scoped_lock支持。

你的代码离使用std::mutex又近了一步。

对于您的unique_ptr解决方案,我不会在每次随意锁定互斥锁时增加内存分配的开销。

最新更新