如何创建一个智能指针锁定和解锁一个互斥?(How can I create a smart poin

2019-08-20 06:24发布

我有一个带螺纹的类从中我想偶尔获得的指针的一个实例变量。 我想这个访问由互斥看守,使线从直到客户端与它的指针完成访问该资源的封锁。

我对这个初始的方法是一对对象返回:一个指针一个shared_ptr的资源之一的锁定对象互斥。 此shared_ptr的保持于锁定对象的唯一引用,以便当它超出范围的互斥应该被解锁。 事情是这样的:

void A::getResource()
{
    Lock* lock = new Lock(&mMutex);
    return pair<Resource*, shared_ptr<Lock> >(
        &mResource, 
        shared_ptr<Lock>(lock));
}

这个解决方案是不理想的,因为它需要在客户端保持到整个对象对。 这样的行为打破了线程安全性:

Resource* r = a.getResource().first;

另外,我自己的实现的,这是死锁,我难以决定的原因,所以有可能是其他的东西错。

我想有是一个包含锁定为一个实例变量,以访问该资源的手段结合它一个shared_ptr。 这似乎喜欢的事,应该有一个既定的设计模式,不过话说做了一些研究,我很惊讶地发现它非常难遇到。

我的问题是:

  • 是否有这种模式的一个常见的实现?
  • 是否有与把一个互斥是我俯瞰,以防止这种模式被广泛的一个shared_ptr里面的问题?
  • 是否有一个很好的理由不实现自己的shared_ptr类来实现这种模式?

(注:我正在使用的Qt但不幸的是在这种情况下不能使用boost代码库。但是,涉及升压答案仍然是人们普遍关心的。)

Answer 1:

我不知道是否有任何标准的实施,但因为我喜欢重新实现的东西没有理由,这里是应该工作(假设你不希望能够复制这样的指针)的一个版本:

template<class T>
class locking_ptr
{
public:
  locking_ptr(T* ptr, mutex* lock)
    : m_ptr(ptr)
    , m_mutex(lock)
  {
    m_mutex->lock();
  }
  ~locking_ptr()
  {
    if (m_mutex)
      m_mutex->unlock();
  }
  locking_ptr(locking_ptr<T>&& ptr)
    : m_ptr(ptr.m_ptr)
    , m_mutex(ptr.m_mutex)
  {
    ptr.m_ptr = nullptr;
    ptr.m_mutex = nullptr;
  }

  T* operator ->()
  {
    return m_ptr;
  }
  T const* operator ->() const
  {
    return m_ptr;
  }
private:
  // disallow copy/assignment
  locking_ptr(locking_ptr<T> const& ptr)
  {
  }
  locking_ptr& operator = (locking_ptr<T> const& ptr)
  {
    return *this;
  }
  T* m_ptr;
  mutex* m_mutex; // whatever implementation you use
};


Answer 2:

你描述的变化进行以指针模式,通过凯夫林·海尼在描述执行大约序列 。

我曾在某原型实现exec_around.h ,但我不能保证它正常工作在所有情况下,因为它的工作正在进行中。 它包括一个功能mutex_around它创建一个对象,并把它包装在智能指针锁和被访问时解锁互斥。



Answer 3:

这里有另一种方法。 远不如灵活而且不通用,也简单得多。 虽然它似乎仍然满足您的实际情况。

shared_ptr (包括标准和加速 )提供手段来构建它同时提供另一个shared_ptr实例,该实例将用于使用计数器并不会在所有被管理的一些任意的指针。 在cppreference.com它是第八形式( 混叠构造函数 )。

现在,通常,这种形式用于转化-像提供shared_ptr从派生类对象的基类对象。 他们分享的所有权和使用计数器,但(一般)有不同类型的两个不同的指针值。 这种形式也可以用来提供一个shared_ptr基于成员值shared_ptr到对象,它是一个成员。

在这里,我们可以“滥用”的形式提供锁定挡板。 像这样做:

auto A::getResource()
{
    auto counter = std::make_shared<Lock>(&mMutex);
    std::shared_ptr<Resource> result{ counter, &mResource };
    return result;
}

返回shared_ptrmResource并保持mMutex锁定,只要它由任何人。

这种解决方案的问题是,它现在是你的责任,以确保mResource仍然有效(特别是-它不会破坏)那么久也。 如果锁定mMutex是足够的,那么你的罚款。

否则,上述解决方案必须进行调整,以您的特定需求。 例如,你可能希望有counter的简单struct ,保持双方的Lock ,另一个shared_ptrA对象拥有的mResource



文章来源: How can I create a smart pointer that locks and unlocks a mutex?