Потоковая реализация шаблона наблюдателя - C ++ - PullRequest
0 голосов
/ 28 апреля 2009

Я разрабатываю программу на C ++, в которой есть метод «сканирования», который запускает относительно длительную процедуру сканирования. Когда процедура будет завершена, метод сканирования уведомит наблюдателей о результатах, используя шаблон наблюдателя.

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

Судя по библиотеке потоков поддержки, похоже, что я могу сделать что-то вроде этого:

#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/bind.hpp>
#include <iostream>

boost::mutex io_mutex;

void scan(int scan_target, vector<Listener> listeners)  
{
  //...run scan 
  {
    boost::mutex::scoped_lock  
      lock(io_mutex);
    std::cout << "finished scan" << endl;
    // notify listeners by iterating through the vector
    // and calling "notify()

  }
}

int main(int argc, char* argv[])
{

  vector<Listener> listeners
  // create 
  boost::thread thrd1(
    boost::bind(&scan, 1, listeners));
  boost::thread thrd2(
    boost::bind(&scan, 2, listeners));
  //thrd1.join();
  //thrd2.join();
  return 0;
} 

Это выглядит примерно правильно? Нужно ли мьютекс звонить слушателям? Это нормально, чтобы избавиться от соединений?

Ответы [ 3 ]

1 голос
/ 28 апреля 2009

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

0 голосов
/ 28 апреля 2009

Ваш Listener :: Notify () вызывается из нескольких потоков, поэтому, если Notify () не имеет побочных эффектов, вам придется выполнить одно из трех:

  1. Внешняя блокировка (ваш пример): получение мьютекса перед вызовом Listener :: Notify ()
  2. Внутренняя блокировка: Listener :: Notify () получит внутреннюю блокировку
  3. Lock free: поиск "алгоритм без блокировки" в Google

Есть плюсы / минусы для каждого варианта ...

Для того, что (я думаю) вам нужно, подойдет вариант 1.

И вам придется сохранить операторы объединения, иначе ваша функция main () может завершиться, прежде чем ваши потоки смогут завершить свою работу. Также рассмотрите возможность использования boost::thread_pool и joint_all.

0 голосов
/ 28 апреля 2009

Я не знаю, что такое повышение, но концептуально это выглядит правильно. У вас есть наблюдатели, которые хотят получать уведомления об изменениях состояния. Когда происходит «квалификационное событие», вы должны пройти список (или вектор, что-то в этом роде) наблюдателей, чтобы уведомить. Вы также хотите убедиться, что одновременные уведомления не доставляют вам хлопот,

(Вот статья Википедии e на схеме.)

...