我们有很多遗留的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解决方案,我不会在每次随意锁定互斥锁时增加内存分配的开销。