Поведение RAII :: scoped_lock

Из Контейнер класс, я бы хотел lock вектор boost::mutexкаждый из которых принадлежит Управляемая экземпляр (странный дизайн кода, но только для целей 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 связан с процессором и Управляемая В то же время объекты модифицируются из других мест, я хотел бы просто сделать циклический scoped_lock в начале main_methodдля того, чтобы заблокировать все а также Срочно, такие как

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 цикл заканчивается

Я пытался new массив замков в Контейнер ctor и to delete это в его dtor, но я думаю, что это против самой идиомы RAII.

Что я неправильно понял, или как я мог реорганизовать всю проблему?

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

Другие решения

Как насчет следующего?

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

Вы уже можете использовать бесплатные расширения функций из Boost Thread для атомарной блокировки коллекции отложенных блокировок:

Жить на Колиру

#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);
}
0
По вопросам рекламы [email protected]