использование мьютексов и condition_variables

Я ищу правильный шаблон взаимосвязи между двумя потоками, используя библиотеку межпроцессного взаимодействия. Я не думаю, что для библиотеки есть что-то особенное, в отличие от типичного параллельного программирования с использованием стандартной библиотеки. Поэтому я ищу базовую технику и понимание использования этих примитивов синхронизации.

Есть два потока: записывающий и читающий, которые используют общую память. Именованный мьютекс используется для синхронизации доступа к объектам (строкам и векторам) в разделяемой памяти. условная переменная, используемая для ожидания, когда считыватель запишет данные в разделяемую память. Итак, сценарий такой: - запускается считыватель и инициализирует условную переменную на именованном мьютексе с условием, что вектор с данными должен быть непустым. и ждет... - писатель блокирует мьютекс и заполняет вектор - писатель "уведомляет" о завершении записи в вектор данных и разблокирует мьютекс - читатель получает уведомление, блокирует мьютекс и обрабатывает данные в векторе.

после этого читатель должен сообщить писателю, что чтение завершено и вектор можно снова заполнить новой порцией данных.

поэтому я не уверен, как правильно настроить все эти ожидания и уведомления. Похоже, моя версия делает тупик. Пожалуйста, порекомендуйте.

код читательского потока

    namespace bi = boost::interprocess;
    using bi_char_vector = bi::vector<char, CharAllocator>;

    bi::named_mutex             mtx{bi::open_or_create, "mtx"};
    bi::named_condition         cnd{bi::open_or_create, "cnd"};

    data = segment.find_or_construct<bi_char_vector>("data")(segment.get_segment_manager());
    while (!done) {
       bi::scoped_lock<bi::named_mutex> lock{mtx};
       cnd.wait(lock, [data] {return !data->empty(); });

       // process the data...

       cnd.notify_one();
    }

код авторской темы:

    bi::managed_shared_memory segment(bi::open_only, shm_name.c_str());
    bi::named_mutex mtx{bi::open_only, "mtx"};
    bi::named_condition cnd(bi::open_only, "cnd");

    data = segment.find_or_construct<bi_char_vector>("data")(segment.get_segment_manager());

    for(std::size_t chunk_num = 0; chunk_num < chunk_count; ++chunk_num) {
        bi::scoped_lock<bi::named_mutex> lock { mtx };
        cnd.wait(lock);
        data->clear();
        // fills the data
        cnd.notify_one();
    }
}

если я устанавливаю ожидание в цикле записи, он останавливается на этом, если я удаляю это ожидание, похоже, что читатель получает и обрабатывает только последнюю итерацию цикла


person amigo421    schedule 22.12.2015    source источник


Ответы (1)


нашел проблему. со стороны читателя добавил:

while (!done) {
   bi::scoped_lock<bi::named_mutex> lock{mtx};
   cnd.wait(lock, [data] {return !data->empty(); });

   // process the data...

   data->clear();
   cnd.notify_one();
}

на стороне писателя:

    for(std::size_t chunk_num = 0; chunk_num < chunk_count; ++chunk_num) {
        bi::scoped_lock<bi::named_mutex> lock { mtx };
        cnd.wait(lock, [data] {return data->empty(); });
        //...
        cnd.notify_one();
    }

и теперь он работает, как ожидалось

person amigo421    schedule 22.12.2015