Convert C # lock keyword in C ++

How can I implement the C # lock keyword in C ++? The code in C # is as follows:

try { lock (matrixLock) { ThisTransformation.get_Renamed(matrix); } } 
+4
source share
8 answers

The C # lock keyword is not a mutex . Instead, it calls Monitor::Enter() Try this. Also see the MSDN link .

  // 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); } 

Note. This answer assumes that you are configuring the C ++ CLI.

+4
source

A. - Quick response

Assuming you have a Mutex and Lock object (your mileage may vary):

 #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) 

which can be used as:

 Mutex mutex ; void foo() { // not locked MY_OWN_LOCK(mutex) { // locked } // not locked } 

B. - Detailed answer

It depends on the library you will be using.

B.1 - Prerequisites

Suppose you have:

  • a Mutex object that has lock() and unlock() methods
  • a Lock , which has a constructor with the Mutex as parameter and calls its lock() method when building, and the unlock() method when it is destroyed

So you have something like:

 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 - Using Raw C +

If you are not familiar with C ++ RAII, your code will look like this:

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

This code is so flawed that I will never discuss it (Google "exception safety" if necessary).

B.3 - Using Raw C ++

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

B.4 - Using C ++ with Macro Photography

With the following macro:

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

You can write:

 void foo() { // not locked LOCK(mutex) { // locked ! } // not locked } 

B.5 - Why is it so complicated?

Most lock macros rely on the lock object to be tested. This either requires the implementation of Safe Bool Idiom (which is redundant for current use), or the need to lock the lock object for bool , which brings its own (large) set of flaws to the class.

In the current implementation, if used to declare a logical element that will control the body of for , while for itself is used to declare the Lock object itself.

I believe this template is called something like "C ++ variable injection."

B.6 - Performance?

Please note that you are blocking something, so the code inside mutex.lock() and mutex.unlock() will take much more cycles than anything in the macro.

In non-optimized assemblies, if and for jumps will be displayed (for example, try phasing in the visual debugger), but in an optimized assembly all if and for will be optimized (there is no difference between the assembly generated by "raw C ++ usage" and "using using extended C ++ macros. "

B.7 - Attention!

The macro above is simplified for educational purposes. To use it for production code, you must:

  • "namespace" is the name of the macro (that is, prefixing it with some unique name, like BOOST_ part of the macro BOOST_FOREACH )
  • make logical b and Lock variable "unique" to make sure that they will not interfere with the user code. I usually use the suffix GUID / UUID for this (e.g. b_ABCD_ABCD_AB_ABCDEF and lock_ABCD_ABCD_AB_ABCDEF )

B.8 - Sources

I first saw this model in an article (I believe Andrei Alexandrescu), and indeed, I was looking for it when I came across this SO question.

:-)

As soon as I find the source, I will update this answer with the correct link.

Edit: Source found !!!

+4
source

You can use boost::mutex and boost::scoped_lock to do this:

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

You can use macros and for-loops to give you the lock keyword, although I would strongly advise you not to do this, as this will break the code that is used to use lock as an identifier.

+3
source

Here is all you need: Implementing the lock keyword in C ++

C ++ does not have the lock keyword, but you can do it yourself. Given the Mutex class, which has the Lock () and Unlock () functions (and possibly IsLocked () for convenience), most C ++ programmers immediately wrote AutoLock, something like this:

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

A typical use of this thing would look like this:

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

But with a simple preprocessor trick, you can make the syntax identical with C #:

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

C ++ does not have a lock keyword. You can use mutexes .

+1
source

You cannot, such a keyword does not exist, the closest thing you get is the acceleration of the locked lock (which the boost mutex can use).

+1
source

I would use the Boost library library . If you cannot for some reason, I would hack something like this:

 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: This code did not go through the compiler. YMMV.

This code allows you to do such things:

 class SomeClass { CriticalSection m_cs; SomeResource m_resource; public: void SomeOperation() { CriticalSectionLocker lock(m_cs); m_resource.DoSomething(); } }; 

The lock is locked in the scope of SomeClass::SomeOperation() . You can also release the lock by calling its Unlock() method if you no longer need to hold the lock.

This code is in no way generalized. It can be removed using the awesomeness template and made general enough to use mutexes and other objects of the operating system. But if you want to go there, I would recommend using boost libraries.

+1
source

I searched the same thing from C # background and came across this question several times. I know this many years after its request, but now with C ++ 11 you can use std :: lock_guard and the syntax has become very similar to C #

where in c # do you have

 object syncObj; ... lock(syncObj){ ... } 

in C ++ 11 you can use mutex as synchronization and lock_guard is similar to locking

 std::mutex m; ... std::lock_guard<std::mutex> lock(m);{...} 

If you

 #define lock(mutex) std::lock_guard<std::mutex> lock(mutex); 

then it will look the same :)

0
source

Source: https://habr.com/ru/post/1334088/


All Articles