Mutex的锁定/解锁功能应该是"const"吗?

use*_*610 9 c++ api multithreading

我正在维护一个包含Mutex类的库.我无法确定此类公开的lock()和unlock()函数是否应该是const.我在Web上寻找类似的代码,并且可以找到这两种实现.

第一个实现,lock()和unlock()不是const.这意味着在const函数中使用Mutex类的人应该付出额外的努力来调用Mutex的函数:

class Mutex
{
public:
   void lock();
   void unlock();
};

class Foo
{
public:
   void getBar(Bar& bar) const
   {
      m_mutex.lock();
      bar = m_bar;
      m_mutex.unlock();
   }

private:
   // Mutable, responsability of the user (or we could use a const_cast when needed)
   mutable Mutex m_mutex;
   Bar   m_bar;
};
Run Code Online (Sandbox Code Playgroud)

第二个实现,lock()和unlock()是const,即使这听起来不太自然(因为我们修改了Mutex实例),但用户在他的一个const函数中调用这些函数时不必费心:

class Mutex
{
public:
   void lock() const;
   void unlock() const;
};

class Foo
{
public:
   void getBar(Bar& bar) const
   {
      m_mutex.lock();
      bar = m_bar;
      m_mutex.unlock();
   }

private:
   Mutex m_mutex;
   Bar   m_bar;
};
Run Code Online (Sandbox Code Playgroud)

你更喜欢什么解决方案?我希望你的意见能帮助我做出决定.

GMa*_*ckG 10

mutable这是为了这种东西.即,mutable适用于不参与对象的逻辑const的事物.(如果一个值是"逻辑常数",则表示"主要"值是常量;对象的值从外部不能更改.)

对象的值独立于互斥锁的状态(它只是提供一致性的实现细节,并且它的状态在类外是未知的),这是你的互斥锁应该是一个好兆头mutable.


注意,你不应该去const_cast路线.如果你这样做,这会导致未定义的行为:

const Foo f;

Bar b;
f.getBar(b); // takes const off of mutex, modifies (bang you're dead)
Run Code Online (Sandbox Code Playgroud)


Nav*_*een 8

我更喜欢Mutex mutable在客户端代码中创建第一个选项.这样,该类的用户明确地知道他正在从他的const函数调用非const函数.实际上,如果您看到CMutex类的MFC实现,您可以看到Lock并且Unlock方法是非const的.


zac*_*sek 0

如果您想从 Mutex 类派生类,那么将这两个函数设置为 const 是有意义的,然后您可以在派生类自己的 const 函数中调用它。

像这样:

class Foo : public Mutex {
public:
    void
        bar() const { lock(); doSomething(); unlock(); }
}
Run Code Online (Sandbox Code Playgroud)