首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为定制库实现lock_guard的适当C++方式

为定制库实现lock_guard的适当C++方式
EN

Stack Overflow用户
提问于 2017-03-06 14:26:43
回答 3查看 3.5K关注 0票数 0

O明智的互连网

我们有两个同事之间的僵局,我们需要你的帮助,以适当的C++方式解决。基本上,我们有一组实用程序类,其中两个是Mutex和SpinLock类,它们都有以下简化的接口:

代码语言:javascript
复制
class Mutex {
public:
    Mutex();
    ~Mutex();
    void Lock();
    void Unlock();
    // ...
};

显然,这与std::lock_guard使用的BasicLockable概念类似,但大小写不同,所以我们需要类似的概念(假设本例中的互斥类是不可变的;我们不能向其添加BasicLockable概念)。此外,并非所有支持平台的编译器都具有完整的c++11特性,因此我们不能只使用普通的c++11支持。

一种思想流派是下面的通用守卫类的实现,它可以被继承来提供通用守卫类,并从它继承来创建锁守卫类:

代码语言:javascript
复制
template<class T, void (T::*EnterFn)(), void (T::*ExitFn)()>
class Guard
{
public: // copy constructor deleting omitted for brevity
    Guard( T *lock ) : m_lock(lock) { (m_lock->*EnterFn)(); }
    ~Guard();                       { (m_lock->*ExitFn)(); }
private:
    T *m_lock;
};

template<class T>
class LockGuard : public Guard<T, &T::Lock, &T::Unlock>
{
public:
    LockGuard(const T* lock) : Guard<T, &T::Lock, &T::Unlock>(lock) {}
};

另一种思想是实现一个简单的lockguard:

代码语言:javascript
复制
template<class T>
class LockGuard {
    T* m_lockable;
public:
    LockGuard(const T* lockable) : m_lockable(lockable) { lockable->Lock(); }
    ~LockGuard() { m_lockable->Unlock(); }
};

您会选择哪种实现?为什么?实现它的最合适的C++(03,11,14,17)方式是什么?如上所述,拥有一个通用的Guard类有什么固有的价值吗?

EN

回答 3

Stack Overflow用户

发布于 2017-03-06 23:01:56

我不想使用方法指针。

就我个人而言,我希望尽可能多地转向C++11标准工具。所以我会写一个适配器。

代码语言:javascript
复制
template<class T>
struct lock_adapter {
  T* t = nullptr;
  void lock() { t->Lock(); }
  void unlock() { t->Unlock(); }
  lock_adapter( T& tin ):t(std::addressof(tin)) {}
  // default some stuff if you like
};

template<class T>
struct adapted_unique_lock:
  private lock_adapter<T>,
  std::unique_lock< lock_adapter<T> >
{
  template<class...Args>
  adapted_unique_lock(T& t, Args&&...):
    lock_adapter<T>(t),
    std::unique_lock< lock_adapter<T> >( *this, std::forward<Args>(args)... )
  {}
  adapted_unique_lock(adapted_unique_lock&&)=delete; // sadly
  friend void swap( adapted_unique_lock&, adapted_unique_lock& ) = delete; // ditto
};

现在,adapted_unique_lockstd::unique_lock获得了一组受限的功能。

它不能移动,因为unique_lock在其实现中持有指向this的指针,并且不会重新放置它。

请注意,整个unique_lock构造函数集的丰富性都是可用的。

返回经过调整的唯一锁的函数必须在作用域结束之前将它们的返回值存储在类似auto&&引用的内容中,并且在C++17之前不能通过链返回它们。

但是,一旦adapted_unique_lock被更改为支持unique_lock.lock(),任何使用T的代码都可以替换为使用.lock()。这将使您的代码库更接近标准的C++11,而不是定制的。

票数 1
EN

Stack Overflow用户

发布于 2020-08-18 05:08:11

我将回答你题目中的问题,因为没有其他人回答。

根据the docs的说法,lock_guard可以在任何“满足BasicLockable要求”的类型上工作。BasicLockable只需要两个方法:lock()unlock()

为了使lock_guard与定制库一起工作,您需要将lock()unlock()方法添加到库的互斥锁类中,或者将其包装在具有lock()unlock()方法的另一个类中。

票数 1
EN

Stack Overflow用户

发布于 2017-03-06 14:38:00

如果你有C++11编译器,你应该使用那些: std::mutex,std::shared_lock,std::unique_lock,std::timed_mutex,std::shared_mutex,std::recursive_mutex,std::shared_timed_mutex,std::recursive_timed_mutex,std::lock_guard。否则它会更复杂,问题上的标签c++11应该被删除。

你不能用C\C++的方式实现自旋锁或互斥锁,你需要添加汇编程序或内部代码-使其不可移植,除非你为每个平台实现它-并且使用许多x86-64 C++11和更高版本的编译器,你不能做内联汇编。

如果你使用固有的锁定逻辑,你会遇到的主要问题是互斥锁或自旋锁后面的对象是不可复制的。一旦你复制了它,或者如果你复制了防御变量,它就会停止被锁定。实现互斥机制的对象也是不可复制的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42618868

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档