Параллельное программирование на С++ в действии. Практика разработки многопоточных программ - [164]

Шрифт
Интервал

диспетчера нельзя

>                                       │копировать

> dispatcher(dispatcher const&)=delete;←┘

> dispatcher& operator=(dispatcher const&)=delete;

> template<

>  typename Dispatcher,│Разрешить экземплярам

>  typename Msg,       │TemplateDispatcher доступ

>  typename Func>     ←┘к закрытым частям класса

> friend class TemplateDispatcher;

> void wait_and_dispatch()

> {          (1) В цикле ждем и диспетчеризуем

>  for (;;) {←┘сообщения

>   auto msg = q->wait_and_pop();

>   dispatch(msg);

>  }

> }              (2) dispatch() смотрит, не пришло ли

>                 │сообщение close_queue, и, если

> bool dispatch (←┘да, возбуждает исключение

>  std::shared_ptr const& msg) {

>  if (dynamic_cast*>(msg.get())) {

>   throw close_queue();

>  }

>  return false;

> }


>public:                          │Экземпляры диспетчера

> dispatcher(dispatcher&& other):←┘можно перемещать

>  q(other.q), chained(other.chained) {│Объект-источник не должен

>  other.chained = true;              ←┘ждать сообщений

> }


> explicit dispatcher(queue* q_): q(q_), chained(false) {}


> template

> TemplateDispatcher

> handle(Func&& f)←┐Сообщения конкретного типа

> {               (3) обрабатывает TemplateDispatcher

>  return TemplateDispatcher(

>   q, this, std::forward(f));

> }


> ~dispatcher() noexcept(false)←┐Деструктор может

> {                            (4) возбудить исключение

>  if (!chained) {

>   wait_and_dispatch();

>  }

> }

>};

>}

Экземпляр >dispatcher, возвращенный функцией >wait(), немедленно уничтожается, так как является временным объектом, и, как уже было сказало, вся работа выполняется в его деструкторе. Деструктор вызывает функцию >wait_and_dispatch(), которая в цикле (1) ожидает сообщения и передает его функции >dispatch(). Сама функция >dispatch()(2) проста, как правда: она проверяет, не получено ли сообщение типа >close_queue, и, если так, то возбуждает исключение; в противном случае возвращает >false, извещая, что сообщение не обработало. Именно из-за исключения >close_queue деструктор и помечен как >noexcept(false)(4); без этой аннотации действовала бы подразумеваемая спецификация исключений для деструктора — >noexcept(true), означающая, что исключения не допускаются, и тогда исключение >close_queue привело бы к завершению программы.

Но просто вызывать функцию >wait() особого смысла не имеет — как правило, нам нужно обработать полученное сообщение. Для этого предназначена функция-член >handle()(3). Это шаблон, и тип сообщения нельзя вывести, поэтому необходимо явно указать, сообщение какого типа обрабатывается, и передать функцию (или допускающий вызов объект) для его обработки. Сама функция >handle() передает очередь, текущий объект >dispatcher и функцию-обработчик новому экземпляру шаблонного класса >TemplateDispatcher, который обрабатывает сообщения указанного типа. Код этого класса показан в листинге С.5. Именно поэтому мы проверяем флаг >chained в деструкторе перед тем, как приступить к ожиданию сообщения; он не только предотвращает ожидание объектами, содержимое которых перемещено, но и позволяет передать ответственность за ожидание новому экземпляру >TemplateDispatcher.


Листинг С.5. Шаблон класса >TemplateDispatcher

>namespace messaging {

>template<

> typename PreviousDispatcher, typename Msg, typename Func>

>class TemplateDispatcher {

> queue* q;

> PreviousDispatcher* prev;

> Func f;

> bool chained;


> TemplateDispatcher(TemplateDispatcher const&) = delete;

> TemplateDispatcher& operator=(

>  TemplateDispatcher const&) = delete;


> template<

>  typename Dispatcher, typename OtherMsg, typename OtherFunc>

> friend class TemplateDispatcher;←┐Все конкретизации

> void wait_and_dispatch()         │TemplateDispatcher

> {                                │дружат между собой

>  for (;;) {

>   auto msg = q->wait_and_pop();

>   if (dispatch(msg))←┐Если мы обработали

>   break;             │сообщение выходим

>  }                  (1) из цикла

> }


> bool dispatch(std::shared_ptr const& msg) {

>  if (wrapped_message* wrapper =

>   dynamic_cast*>(

>   msg.get())) {       ←┐Проверяем тип

>   f(wrapper->contents);│сообщения и

>   return true;         │вызываем

>  }                    (2) функцию

>  else {

>   return prev->dispatch(msg);←┐Вызываем предыдущий

>  }                           (3) диспетчер в цепочке

> }


>public:

> TemplateDispatcher(TemplateDispatcher&& other):

>  q(other.q), prev(other.prev), f(std::move(other.f)),

>  chained(other.chained) {

>  other.chained = true;

> }


> TemplateDispatcher(

>  queue* q_, PreviousDispatcher* prev_, Func&& f_):

>  q(q_), prev(prev_), f(std::forward(f_)), chained(false)

> {

>  prev_->chained = true;

> }


> template

> TemplateDispatcher

> handle(OtherFunc&& of)←┐Дополнительные обработчики

> {                     (4) можно связать в цепочку

>  return TemplateDispatcher<

>   TemplateDispatcher, OtherMsg, OtherFunc>(

>    q, this, std::forward(of));

> }


> ~TemplateDispatcher() noexcept(false)←┐Деструктор снова

> {                                     │


Еще от автора Энтони Д Уильямс
Викиномика. Как массовое сотрудничество изменяет всё

Это знаменитый бестселлер, который научит вас использовать власть массового сотрудничества и покажет, как применять викиномику в вашем бизнесе. Переведенная более чем на двадцать языков и неоднократно номинированная на звание лучшей бизнес-книги, "Викиномика" стала обязательным чтением для деловых людей во всем мире. Она разъясняет, как массовое сотрудничество происходит не только на сайтах Wikipedia и YouTube, но и в традиционных компаниях, использующих технологии для того, чтобы вдохнуть новую жизнь в свои предприятия.Дон Тапскотт и Энтони Уильямс раскрывают принципы викиномики и рассказывают потрясающие истории о том, как массы людей (как за деньги, так и добровольно) создают новости, изучают геном человека, создают ремиксы любимой музыки, находят лекарства от болезней, редактируют школьные учебники, изобретают новую косметику, пишут программное обеспечение и даже строят мотоциклы.Знания, ресурсы и вычислительные способности миллиардов людей самоорганизуются и превращаются в новую значительную коллективную силу, действующую согласованно и управляемую с помощью блогов, вики, чатов, сетей равноправных партнеров и личные трансляции.


Рекомендуем почитать
Изучаем Java EE 7

Java Enterprise Edition (Java EE) остается одной из ведущих технологий и платформ на основе Java. Данная книга представляет собой логичное пошаговое руководство, в котором подробно описаны многие спецификации и эталонные реализации Java EE 7. Работа с ними продемонстрирована на практических примерах. В этом фундаментальном издании также используется новейшая версия инструмента GlassFish, предназначенного для развертывания и администрирования примеров кода. Книга написана ведущим специалистом по обработке запросов на спецификацию Java EE, членом наблюдательного совета организации Java Community Process (JCP)


Программное обеспечение и его разработка

Автор книги — американский специалист по программированию, один из руководителей фирмы IBM, в своей книге делает попытку изложить общие проблемы создания программного обеспечения, его сопровождения и использования. Особенно подробно рассматриваются все фазы разработки программ разных типов. Изложение ясное, удачно иллюстрировано примерами.Для программистов разной квалификации и пользователей ЭВМ.fb2: ВНИМАНИЕ. В тексте присутствуют таблицы. Рекомендуется читать файл с помощью программы, поддерживающей их отображение.


Вариации на тему STL. Адаптер обобщенного указателя на функцию-член класса

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


Примеры использования Паттерн Singleton (Одиночка)

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


Создаем порт для FreeBSD своими руками. Часть II

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


FreeBSD - полезные советы

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