volatile关键字和RAII习语(C ++)

时间:2015-02-02 22:35:42

标签: c++ volatile raii

假设有一个类来控制与此类似的(关键)代码块的并发访问:

class RAIIObj : public boost::noncopyable {
public:
    explicit RAIIObj( LockObj& Obj ) : LkObj( Obj ) { Obj.Acquire(); }
    ~RAIIObj() { try { Obj.Release(); } catch (...) {} }
private:
    LockObj& LkObj;
};

使用这样的代码时,是否需要按顺序使用volatile关键字 不要看到代码被优化了吗?

例如,我是否必须写

ALockingObj LockObj;

void AFunc() {
    RAIIObj LKGuard( LockObj );

    // do some MT stuff
}

ALockingObj LockObj;

void AFunc() {
    volatile RAIIObj LKGuard( LockObj );

    // do some MT stuff
}

为了确保LKGuard始终存在?

由于LKGuard是一个局部变量,不会在身体的任何一点使用 如果我不使用volatile关键字,可以优化该函数吗?

由于

2 个答案:

答案 0 :(得分:6)

不,你不需要声明它是不稳定的。编译器可以看到实例化lkobj做了一大堆不能优化的东西(而不是int lkobj;,它显然什么也没做)

答案 1 :(得分:0)

虽然pm100提供的答案在标准方面确实是正确的,但我发现GCC 4.9可以优化RAII类型(优化标志:-Os -flto)。这是优化器丢弃的代码:

class MutexLocker
{
    chibios_rt::Mutex& mutex_;
public:
    MutexLocker(chibios_rt::Mutex& m) : mutex_(m)
    {
        mutex_.lock();
    }
    ~MutexLocker()
    {
        mutex_.unlock();
    }
};

使类型volatile解决了问题:

namespace impl_
{
    class MutexLockerImpl
    {
        chibios_rt::Mutex& mutex_;
    public:
        MutexLockerImpl(chibios_rt::Mutex& m) : mutex_(m)
        {
            mutex_.lock();
        }
        ~MutexLockerImpl()
        {
            mutex_.unlock();
        }
    };
}
using MutexLocker = volatile impl_::MutexLockerImpl;

因此,尽管标准不要求这样做,但我建议明确声明RAII类型是易变的,以便考虑积极的优化。