Из Контейнер класс, я бы хотел 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.
Что я неправильно понял, или как я мог реорганизовать всю проблему?
Предполагая, что ваш вопрос: «Как я могу использовать 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);
}
}
Как насчет следующего?
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 для атомарной блокировки коллекции отложенных блокировок:
#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);
}