将C#的lock关键字转换为C++

Rav*_*ngh 7 c# c++ visual-studio-2008 visual-studio

如何在C++中实现C#的lock关键字?c#中的代码如下:

try
{
  lock (matrixLock)
  {
    ThisTransformation.get_Renamed(matrix);
  }
}
Run Code Online (Sandbox Code Playgroud)

pae*_*bal 5

A. - 快速回答

假设您有一个Mutex和一个Lock对象(您的里程可能会有所不同):

#define MY_OWN_LOCK(mm_mutex)                                         \
                                                                      \
    if(bool b_1227F2B8_136B_11E1_973D_7D0B4924019B = false)           \
        ;                                                             \
    else                                                              \
        for(Lock lock_1227F2B8_136B_11E1_973D_7D0B4924019B(mm_mutex); \
            !b_1227F2B8_136B_11E1_973D_7D0B4924019B;                  \
            b_1227F2B8_136B_11E1_973D_7D0B4924019B = true)
Run Code Online (Sandbox Code Playgroud)

可以用作:

Mutex mutex ;

void foo()
{
    // not locked

    MY_OWN_LOCK(mutex)
    {
       // locked
    }

    // not locked
}
Run Code Online (Sandbox Code Playgroud)

B. - 详细解答

这取决于您将使用的库。

B.1 - 先决条件

让我们假设你有:

  • 一个Mutex对象,它有一个lock()和一个unlock()方法
  • 一个Lock对象,它有一个带Mutex参数的lock()构造函数,在构造时调用它的方法,unlock()在析构时调用它的方法

所以,你有这样的事情:

class Mutex
{
    public :
        lock() ;
        unlock() ;
        // etc.
} ;

class Lock
{
    Mutex & m_mutex ;
    public :
        Lock(Mutex & p_mutex) : m_mutex(p_mutex)
            { this->m_mutex.lock() ; }
        ~Lock()
            { this->m_mutex.unlock() ; }
        // etc.
} ;
Run Code Online (Sandbox Code Playgroud)

B.2 - 原始 C+ 使用

如果您不熟悉 C++ 的 RAII,您的代码将类似于:

void foo()
{
   // not locked
   mutex.lock() ;
   // locked !
   mutex.unlock() ;
   // not locked
}
Run Code Online (Sandbox Code Playgroud)

这段代码太错误了,我永远不会讨论它(如果需要,谷歌“异常安全”)。

B.3 - 原始 C++ 的使用

void foo()
{
   // not locked
   {
      Lock lock(mutex) ;
      // locked !
   }
   // not locked
}
Run Code Online (Sandbox Code Playgroud)

B.4 - 宏增强的 C++ 使用

使用以下宏:

#define LOCK(mm_mutex)                                     \
                                                           \
                 if(bool b = false)                        \
                    ;                                      \
                 else                                      \
                    for(Lock lock(mm_mutex); !b; b = true)
Run Code Online (Sandbox Code Playgroud)

你将能够写:

void foo()
{
   // not locked

   LOCK(mutex)
   {
      // locked !
   }

   // not locked
}
Run Code Online (Sandbox Code Playgroud)

B.5 - 为什么这么复杂?

大多数锁宏依赖于锁对象是可测试的。这要么需要Safe Bool Idiom的实现(这对当前使用来说太过分了),要么需要将锁定对象强制转换为bool,这给类带来了自己的(大)缺陷集。

在当前的实现中,if用于声明将控制for的主体执行的布尔值,而for本身用于声明Lock对象本身。

我相信这种模式被称为“C++ 变量注入”。

B.6 - 性能?

请注意,你锁定的东西,所以里面的代码mutex.lock(),并mutex.unlock()会采取更多的周期比任何宏观。

在非优化构建中,将显示iffor跳转(例如,在可视化调试器上逐步尝试),但在优化构建中,整体iffor将被优化掉(“原始”生成的程序集之间没有区别C++ 使用”和“宏增强的 C++ 使用”。

B.7 - 注意!!!

出于教育目的,上面的宏被简化了。要在生产代码中使用它,您必须:

  • “命名空间”宏名称(即在它前面加上某种独特的名称,作为宏的BOOST_一部分BOOST_FOREACH
  • 使布尔值b和 Locklock变量“唯一”以确保它们不会与用户代码发生冲突。我通常为此使用 GUID/UUID 后缀(例如b_ABCD_ABCD_AB_ABCDEFlock_ABCD_ABCD_AB_ABCDEF

B.8 - 来源

我第一次在一篇文章中看到了这种模式(我相信是 Andrei Alexandrescu 写的),事实上,当我偶然发现这个 SO 问题时,我正在寻找它。

:-)

找到来源后,我将使用正确的链接更新此答案。

编辑:找到来源!!!


LaG*_*ere 1

这里有您需要的一切:Implementing a lock keywords in C++

C++ 没有 lock 关键字,但您可以自己创建一个。给定一个具有 Lock() 和 Unlock() 成员函数(为了方便起见可能还有 IsLocked())的 Mutex 类,大多数 C++ 程序员会立即编写一个 AutoLock,有点像这样:

class AutoLock
{
public:
    AutoLock(Mutex& m): m_mutex(m)  { m_mutex.Lock(); }
    ~AutoLock()                     { m_mutex.Unlock(); }
    operator bool()                 { return m_mutex.IsLocked(); }
private:
    Mutex&   m_mutex;
};
Run Code Online (Sandbox Code Playgroud)

正常使用这个东西会是这样的:

{
    AutoLock lock(m_mutex);
    // my protected code here
}
Run Code Online (Sandbox Code Playgroud)

但通过简单的预处理器技巧,您可以使语法与 C# 相同:

#define lock(x) if (!(AutoLock _l = x)); else
Run Code Online (Sandbox Code Playgroud)

  • 天啊。这太糟糕了。除了“if (!(AutoLock _l = x))”在语法上不正确之外,如果您打算用 C++ 编写代码,您应该编写惯用的 C++。 (2认同)