在C ++中模拟C#锁定语句 [英] Emulate C# lock statement in C++

查看:102
本文介绍了在C ++中模拟C#锁定语句的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

简介:对于同步,C#提供了System.Threading.Monitor类,提供了线程同步例程,例如Enter()Exit()TryEnter()等.

此外,还有lock语句可确保在遗留关键代码块时通过正常执行流程或异常来破坏锁:

private static readonly obj = new Object();

lock(obj) {
   ...
}

问题::在C ++中,为此目的,我们获得了RAII包装器std::lock_guardstd::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.Monitorclass, 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#锁定语句的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆