Использование мьютексов и условных переменных

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

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

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

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

код нити читателя

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

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

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

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

Другие вопросы по тегам