boost::scoped_lock RAII 行为

boost::scoped_lock RAII behaviour

从一个容器class,我想lock一个boost::mutex的向量,每个容器都属于一个Controlled 实例(奇怪的代码设计,但仅用于 MWE)。

// std::vector<Controlled*> _vData;

void Container::main_method()
{
  for (int i=0; i<_vData.size(); i++)
  {
    boost::mutex::scoped_lock my_lock(_vData.at(i)->_mutex);
    this->processing(i);
  }

  // precondition for post_processing(): all processing() calls done
  for (int i=0; i<_vData.size(); i++)
  {
    boost::mutex::scoped_lock my_lock(_vData.at(i)->_mutex);
    this->post_processing(i);
  }
}

但是由于 processing 是 cpu-bound 并且同时从其他地方修改了 Controlled 对象,我想简单地做一个在main_method开头循环scoped_lock,为了锁定everythingasap,比如

void Container::desired_main_method()
{
  for (int i=0; i<_vData.size(); i++)
  {
    boost::mutex::scoped_lock my_lock(_vData.at(i)->_mutex);
  }

  // locks destroyed here, aren't they ?

  for (int i=0; i<_vData.size(); i++)
  {
    this->processing(i);
  }

  for (int i=0; i<_vData.size(); i++)
  {
    this->post_processing(i);
  }
}

问题是,如果我很好地理解 RAII 惯用语和 scoped_lock 上下文,那么在锁 for 循环结束后,锁将很快超出范围。

我已经尝试 newContainer ctor 和 delete 它的 dtor 上的锁数组,但我想这是反对的RAII 习语本身。

我误解了什么,或者我该如何重构整个问题?

假设您的问题是:"how do I use a RAII-like scoped lock for multiple mutexes at the same time?"

然后您可以为多个锁创建自己的 RAII 包装器或使用类似 scope guard.

的东西

(未经测试的伪代码,但希望您能理解。)

template <typename TIterator>
class multiple_lock_guard
{
private:
    TIterator _begin, _end;

    multiple_lock_guard(TIterator begin, TIterator end)
        : _begin{begin}, _end{end}
    {
        for(auto it = _begin; it != _end; ++it)
        {
            it->_mutex.lock();
        }
    }

    ~multiple_lock_guard()
    {
        for(auto it = _begin; it != _end; ++it)
        {
            it->_mutex.unlock();
        }
    }
};

您可以按如下方式使用:

void Container::desired_main_method()
{
    multiple_lock_guard mlg(std::begin(_vData), std::end(_vData));

    for(int i = 0; i < _vData.size(); i++)
    {
        this->processing(i);
    }

    for(int i = 0; i < _vData.size(); i++)
    {
        this->post_processing(i);
    }
}

下面的怎么样?

void Container::desired_main_method()
{
  std::vector<boost::mutex::scoped_lock> locks;

  for (int i=0; i<_vData.size(); i++)
  {
    locks.emplace_back(_vData.at(i)->_mutex);
  }

  for (int i=0; i<_vData.size(); i++)
  {
    this->processing(i);
  }

  for (int i=0; i<_vData.size(); i++)
  {
    this->post_processing(i);
  }
}

您已经可以使用 Boost Thread 的免费函数扩展来自动锁定一组延迟锁:

Live On Coliru

#include <boost/thread.hpp>
#include <vector>

struct X {
    boost::mutex mutable mx;
};

void foo(std::vector<X> const& xs) {

    std::vector<boost::unique_lock<boost::mutex> > locks;
    for (auto& x : xs) {
        locks.emplace_back(x.mx, boost::defer_lock);
    }

    boost::lock(locks.begin(), locks.end());

    // all locks held
}

int main() {
    std::vector<X> xs(10);
    foo(xs);
}