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

时间:2011-01-03 16:19:23

标签: c# c++ visual-studio visual-studio-2008

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

try
{
  lock (matrixLock)
  {
    ThisTransformation.get_Renamed(matrix);
  }
}

8 个答案:

答案 0 :(得分:4)

甲。 - 快速回答

假设您有一个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)

可以用作:

Mutex mutex ;

void foo()
{
    // not locked

    MY_OWN_LOCK(mutex)
    {
       // locked
    }

    // not locked
}

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.
} ;

B.2 - 原始C +使用

如果您不熟悉C ++的RAII,您的代码将如下:

void foo()
{
   // not locked
   mutex.lock() ;
   // locked !
   mutex.unlock() ;
   // not locked
}

这段代码是错的,我不会讨论它(谷歌“异常安全”,如果需要的话)。

B.3 - 使用原始C ++

void foo()
{
   // not locked
   {
      Lock lock(mutex) ;
      // locked !
   }
   // not locked
}

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

使用以下宏:

#define LOCK(mm_mutex)                                     \
                                                           \
                 if(bool b = false)                        \
                    ;                                      \
                 else                                      \
                    for(Lock lock(mm_mutex); !b; b = true)

你可以写:

void foo()
{
   // not locked

   LOCK(mutex)
   {
      // locked !
   }

   // not locked
}

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

大多数锁定宏依赖于锁定对象是可测试的。这需要Safe Bool Idiom的实现(对于当前使用来说是过度杀伤),或者需要将锁定对象转换为bool,这会带来自己的(大)缺陷集上课。

在当前实现中,if用于声明控制for正文执行的布尔值,而for本身用于声明{{1}对象本身。

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

B.6 - 表现?

请注意,您正在锁定某些内容,因此Lockmutex.lock()中的代码将比宏中的任何内容占用更多周期。

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

B.7 - 小心!!!

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

  • “namespace”宏名称(即以某种唯一名称作为前缀,作为if宏的for部分)
  • 使布尔BOOST_和锁定BOOST_FOREACH变量“唯一”以确保它们不会与用户代码发生冲突。我通常使用GUID / UUID后缀(例如block

B.8 - 来源

我第一次在文章中看到了这种模式(我相信安德烈亚历山大夫斯库),事实上,当我偶然发现这个问题时,我正在寻找它。

: - )

一旦找到来源,我就会用正确的链接更新这个答案。

编辑:找到源!!!

答案 1 :(得分:3)

您可以使用boost::mutexboost::scoped_lock

boost::mutex matrix_mutex;

// ...
try {
    boost::scoped_lock lock(matrix_mutex);
    // ... everything in this scope is now locked
} // ....

您可以使用宏和for循环为您提供lock关键字,但我强烈建议您不要这样做,因为这会破坏恰好使用lock作为标识符的代码。< / p>

答案 2 :(得分:3)

C#lock关键字不是互斥锁。相反,它会调用Monitor::Enter()试试这个。另请查看MSDN reference

  // Request the lock, and block until it is obtained.
  Monitor::Enter(m_inputQueue);
  try
  {
     // Write your code here.
  }
  finally
  {
     // Ensure that the lock is released.
     Monitor::Exit(m_inputQueue);
  }

注意:此答案假定您的目标是C ++ CLI。

答案 3 :(得分:1)

以下是您需要的一切:Implementing a lock keyword in C++

C ++没有lock关键字,但您可以自己创建一个。给定一个具有Lock()和Unlock()成员函数的Mutex类(为方便起见可能是一个IsLocked()),大多数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;
};

这件事的正常使用看起来像这样:

{
    AutoLock lock(m_mutex);
    // my protected code here
}

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

#define lock(x) if (!(AutoLock _l = x)); else

答案 4 :(得分:1)

C ++没有lock关键字。你可以use a mutex

答案 5 :(得分:1)

你不能,不存在这样的关键词,你得到的最接近的东西是boost scoped lock(可以使用提升互斥锁)。

答案 6 :(得分:1)

我会使用Boost synchronization library。如果由于某些原因你不能,我会这样做:

class CriticalSection {
    CRITICAL_SECTION m_cs;

public:
    CriticalSection() {
        ::InitializeCriticalSection(&m_cs);
    }

    ~CriticalSection() {
        ::DeleteCriticalSection(&m_cs);
    }

    void Lock() {
        ::EnterCriticalSection(&m_cs);
    }

    void Unlock() {
        ::LeaveCriticalSection(&m_cs);
    }
};

class CriticalSectionLocker {
    CriticalSection& m_cs;
    bool m_bLocked;
public:
    CriticalSectionLocker(CriticalSection& cs, bool bLockNow = true) : m_cs(cs), m_bLocked(bLockNow) {
        if(bLockNow)
            m_cs.Lock();
    }

    ~CriticalSectionLocker() {
        if(m_bLocked)
            m_cs.Unlock();
    }

    void Lock() {
        m_cs.Lock();
        m_bLocked = true;
    }

    void Unlock() {
        m_cs.Unlock();
        m_bLocked = false;
    }
};

Caveat Emptor:此代码未通过编译器传递。 YMMV。

此代码允许您执行以下操作:

class SomeClass {
    CriticalSection m_cs;
    SomeResource m_resource;

public:
    void SomeOperation() {
        CriticalSectionLocker lock(m_cs);
        m_resource.DoSomething();
    }
};

锁被锁定在SomeClass::SomeOperation()的范围内。如果您不再需要保持锁定,也可以通过调用Unlock()方法释放锁定。

此代码绝不是一般化的。它可以用模板很棒来整理,并使其足够通用以使用互斥锁和其他操作系统对象。但是如果想去那里,我建议改用boost库。

答案 7 :(得分:0)

您可以使用std::lock_guard

这是该文档中的简化示例:

std::mutex resource_mutex;
...
{
    std::lock_guard<std::mutex> lock(resource_mutex); // The variable name ("lock") doesn't matter since it is not supposed to be used anywhere else.
    ...
    // safe to use resource here
    ...
}