2

From a Container class, I'd like to lock a vector of boost::mutex, each one owned by a Controlled instance (weird code design, but for MWE purpose only).

// 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);
  }
}

But since processing is cpu-bound and Controlled objects are modified from elsewhere in the mean time, I'd like to simply do a cycled scoped_lock at the beginning of the main_method, in order to lock everything and asap, such as

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);
  }
}

Problem is, if I understanded well the RAII idiom and the scoped_lock context, that in this way, the locks would go out of scope soon after the lock for cycle ends.

I've tried to new an array of locks at Container ctor and to delete it at its dtor, but I guess this is against the RAII idiom itself.

What did I misunderstand, or how could I refactor the whole issue?

4

3 回答 3

2

假设您的问题是:“如何同时为多个互斥锁使用类似 RAII 的范围锁?”

然后,您可以为多个锁创建自己的 RAII 包装器,也可以使用范围保护之类的东西。

(未经测试的伪代码,但希望你明白。)

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);
    }
}
于 2016-09-13T07:42:49.343 回答
1

下面的呢?

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);
  }
}
于 2016-09-13T07:49:20.567 回答
1

您已经可以使用 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);
}
于 2016-09-13T08:02:54.043 回答