问题描述
简介:对于同步,C#提供了System.Threading.Monitor
类,提供了线程同步例程,例如Enter()
,Exit()
,TryEnter()
等.
此外,还有lock
语句可确保在遗留关键代码块时通过正常执行流程或异常来破坏锁:
private static readonly obj = new Object();
lock(obj) {
...
}
问题::在C ++中,为此目的,我们获得了RAII包装器std::lock_guard
和std::unique_lock
,它们不适用于Monitor
类,但不适用于满足Lockable
概念的类型.但是,出于以下几个原因,我认为该方法在语法上比C#实现它的方法弱:
您使用无法重复使用的变量名称污染了本地范围.可以通过添加新的作用域(如
)来解决 {
std::unique_lock<std::mutex> lck{ mtx };
...
}
但是我觉得这个表示法看起来很尴尬.更令我困扰的是这是有效的C ++:
std::unique_lock<std::mutex>{ mtx ]; // note there is no name to the lock!
...
因此,如果忘记给锁卫起一个适当的名字,该语句将被解释为类型为std::unique_lock<std::mutex>
的名为"mtx"的变量声明,而没有任何锁!
我想在C ++中实现类似于C#中的lock
语句.在C ++ 17中,可以很容易地做到这一点:
#define LOCK(mutex) if(std::lock_guard<decltype(mutex)> My_Lock_{ mutex }; true)
std::mutex mtx;
LOCK(mtx) {
...
}
问:我如何在C ++ 11/14中实现它?
受StoryTeller的好主意启发,我认为自己找到了一个可行的解决方案,尽管有些骇客":
template <typename T>
struct Weird_lock final : private std::lock_guard<T> {
bool flip;
Weird_lock(T& m) : std::lock_guard<T>{ m }, flip{ true } { }
operator bool() noexcept {
bool old = flip;
flip = false;
return old;
}
};
#define LOCK(mutex) for(Weird_lock<decltype(mutex)> W__l__{ mutex }; W__l__;)
好处是,最后不需要分号.不好的是需要一个额外的bool
,但是从我在godbolt.org中看到的情况来看,编译器无论如何都对此进行了优化.
Intro: For synchronization, C# offers the System.Threading.Monitor
class, offering thread synchronization routines such as Enter()
, Exit()
, TryEnter()
and alike.
Furthermore, there is the lock
statement that makes sure a lock gets destroyed when a critical code block is left, either by normal execution flow or by an exception:
private static readonly obj = new Object();
lock(obj) {
...
}
Problem: In C++, for this purpose, we got the RAII wrappers std::lock_guard
and std::unique_lock
that are not applied to Monitor
classes but to types fulfilling the Lockable
concept. However, I consider this approach syntactically weaker than the way C# implemented it for several reasons:
You pollute the local scope with a variable name that cannot be reused. This can be countered by adding new scopes like
{
std::unique_lock<std::mutex> lck{ mtx };
...
}
But I find this notation rather awkward-looking. What troubles me even more that this is valid C++:
std::unique_lock<std::mutex>{ mtx ]; // note there is no name to the lock!
...
So by forgetting to give a proper name to the lock guard, this statement will be interpreted as a variable declaration named "mtx" of type std::unique_lock<std::mutex>
, without having anything locked!
I want to implement something like the lock
statement from C# in C++. In C++17, this can be accomplished very easily:
#define LOCK(mutex) if(std::lock_guard<decltype(mutex)> My_Lock_{ mutex }; true)
std::mutex mtx;
LOCK(mtx) {
...
}
Q: How can I implement this in C++11/14?
Inspired by StoryTeller's great idea, I think I found a viable solution myself, despite being somewhat a "hack":
template <typename T>
struct Weird_lock final : private std::lock_guard<T> {
bool flip;
Weird_lock(T& m) : std::lock_guard<T>{ m }, flip{ true } { }
operator bool() noexcept {
bool old = flip;
flip = false;
return old;
}
};
#define LOCK(mutex) for(Weird_lock<decltype(mutex)> W__l__{ mutex }; W__l__;)
The good thing is that it doesn't need a semicolon in the end. The bad is the need for an additional bool
, but from what I see in godbolt.org, the compiler optimizes this out anyways.
这篇关于在C ++中模拟C#锁定语句的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!