How can I implement lock keyword of C# in C++? The code in c# is as follows:
try
{
lock (matrixLock)
{
ThisTransformation.get_Renamed(matrix);
}
}
Assuming you have a Mutex
and a 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
}
It depends on the library you'll be using.
Let's assume you have:
Mutex
object, which have a lock()
and an unlock()
methodsLock
object, which have a constructor with a Mutex
as parameter, and calls its lock()
method at construction, and unlock()
method at destructionSo, 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.
} ;
If you are unfamiliar with C++'s RAII, your code will be like:
void foo()
{
// not locked
mutex.lock() ;
// locked !
mutex.unlock() ;
// not locked
}
This code is so wrong I won't ever discuss it (Google "exception safety" if needed).
void foo()
{
// not locked
{
Lock lock(mutex) ;
// locked !
}
// not locked
}
With the following macro:
#define LOCK(mm_mutex) \
\
if(bool b = false) \
; \
else \
for(Lock lock(mm_mutex); !b; b = true)
You'll be able to write:
void foo()
{
// not locked
LOCK(mutex)
{
// locked !
}
// not locked
}
Most lock macros rely on the lock object to be testable. This either needs an implementation of the Safe Bool Idiom (which is overkill for the current use), or the need for the lock object to be castable to bool
, which brings its own (large) set of flaws to the class.
In the current implementation, the if
is used to declared the boolean that will control the for
's body execution, while the for
itself is used to declare the Lock
object itself.
I believe this pattern is called something like "C++ variable injection".
Note that you're locking something, so the code inside the mutex.lock()
and mutex.unlock()
will take a lot more cycles than anything in the macro.
In non-optimized builds, the if
and for
jumps will show (e.g. try it step-by-step on a visual debugger), but in optimized build, the whole if
and for
will be optimized away (there's no difference between the assembly generated by the "raw C++ use" and the "macro-enhanced C++ use".
The macro above is simplified for educational purposes. To use it on production code, you must:
BOOST_
part of the BOOST_FOREACH
macro)b
and the Lock lock
variable "unique" to make sure they won't collide with user code. I usually use a GUID/UUID suffix for that (e.g. b_ABCD_ABCD_AB_ABCDEF
and lock_ABCD_ABCD_AB_ABCDEF
)I first saw that pattern in an article (I believe by Andrei Alexandrescu), and indeed, I was searching for it when I stumbled on this SO question.
:-)
As soon as I find the source, I'll update this answer with the correct link.
Edit: Found the source!!!
You can use boost::mutex
and boost::scoped_lock
for 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 a lock
keyword, although I would strongly advise against doing so, since that will break code that happens to use lock
as an identifier.
The C# lock
keyword is not a mutex. Instead, it calls Monitor::Enter()
Try this. Also look at 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);
}
Note: this answer assumes you are targeting C++ CLI.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With