Поскольку мы не возбуждаем исключения, если сообщение обработало, то теперь в цикле (1) нужно проверять, обработали мы сообщение или нет. Обработка прекращается, как только сообщение успешно обработало, чтобы в следующий раз можно было ждать очередного набора сообщений. Если найдено соответствие указанному типу сообщения, то вызывается предоставленная функция (2), а не возбуждается исключение (хотя функция-обработчик может и сама возбудить исключение). Если же соответствие не найдено, то мы передаем сообщение предыдущему диспетчеру в цепочке (3). В самом первом экземпляре это будет объект dispatcher, но если в функции handle() (4) вызовы сцеплялись, чтобы можно было обработать несколько типов сообщений, то предыдущим диспетчером может быть ранее созданный экземпляр TemplateDispatcher<>, который в свою очередь передаст сообщение предшествующему ему диспетчеру в цепочке, если не сможет обработать его сам. Поскольку любой обработчик может возбудить исключение (в том числе и обработчик самого первого объекта dispatcher, если встретит сообщение close_queue), то деструктор снова необходимо снабдить аннотацией noexcept(false) (5).

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

И чтобы закончить пример из главы 4, в листинге С.6 приведён код сообщений, в листингах С.7, С.8 и С.9 — различные конечные автоматы, а в листинге С.10 — управляющая программа.

Листинг С.6. Сообщения банкомата

struct withdraw {

 std::string account;

 unsigned amount;

 mutable messaging::sender atm_queue;

 withdraw(std::string const& account_,

  unsigned amount_, messaging::sender atm_queue_):

   account(account_), amount(amount_), atm_queue(atm_queue_) {}

};

struct withdraw_ok {};

struct withdraw_denied {};

struct cancel_withdrawal {

 std::string account;

 unsigned amount;

 cancel_withdrawal(std::string const& account_,

  unsigned amount_):

   account(account_), amount(amount_) {}

};

struct withdrawal_processed {

 std::string account;

 unsigned amount;

 withdrawal_processed(std::string const& account_,

  unsigned amount_):

   account(account_), amount(amount_) {}

};

struct card_inserted {

 std::string account;

 explicit card_inserted(std::string const& account_):

  account(account_) {}

};

struct digit_pressed {

 char digit;

 explicit digit_pressed(char digit_):

  digit(digit_) {}

};

struct clear_last_pressed {};

struct eject_card {};

struct withdraw_pressed {

 unsigned amount;

 explicit withdraw_pressed(unsigned amount_):

  amount(amount_) {}

};

struct cancel_pressed {};

struct issue_money {

 unsigned amount;

 issue_money(unsigned amount_):

  amount(amount_) {}

};

struct verify_pin {

 std::string account;

 std::string pin;

 mutable messaging::sender atm_queue;

 verify_pin(std::string const& account_, std::string const& pin_,

  messaging::sender atm_queue_):

   account(account_), pin(pin_), atm_queue(atm_queue_) {}

};

struct pin_verified {};

struct pin_incorrect {};

struct display_enter_pin {};

struct display_enter_card {};

struct display_insufficient_funds {};

struct display_withdrawal_cancelled {};

struct display_pin_incorrect_message {};

struct display_withdrawal_options (};

struct get_balance {

Перейти на страницу:

Похожие книги