Энтони Уильямс - Параллельное программирование на С++ в действии. Практика разработки многопоточных программ
- Название:Параллельное программирование на С++ в действии. Практика разработки многопоточных программ
- Автор:
- Жанр:
- Издательство:ДМК Пресс
- Год:2012
- Город:Москва
- ISBN:978-5-94074-448-1
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Энтони Уильямс - Параллельное программирование на С++ в действии. Практика разработки многопоточных программ краткое содержание
Книга «Параллельное программирование на С++ в действии» не предполагает предварительных знаний в этой области. Вдумчиво читая ее, вы научитесь писать надежные и элегантные многопоточные программы на С++11. Вы узнаете о том, что такое потоковая модель памяти, и о том, какие средства поддержки многопоточности, в том числе запуска и синхронизации потоков, имеются в стандартной библиотеке. Попутно вы познакомитесь с различными нетривиальными проблемами программирования в условиях параллелизма.
Параллельное программирование на С++ в действии. Практика разработки многопоточных программ - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
q, this, std::forward(of));
}
~TemplateDispatcher() noexcept(false)←┐
Деструктор снова
{ │
помечен как
if (!chained) {
(5) noexcept(false)
wait_and_dispatch();
}
}
};
}
Шаблон класса TemplateDispatcher<>
устроен по образцу класса dispatcher
и почти ничем не отличается от него. В частности, деструктор тоже вызывает wait_and_dispatch()
, чтобы дождаться сообщения.
Поскольку мы не возбуждаем исключения, если сообщение обработало, то теперь в цикле (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 {
std::string account;
mutable messaging::sender atm_queue;
get_balance(
std::string const& account_, messaging::sender atm_queue_):
account(account_), atm_queue(atm_queue_) {}
};
struct balance {
unsigned amount;
explicit balance(unsigned amount_):
amount(amount_) {}
};
struct display_balance {
unsigned amount;
explicit display_balance(unsigned amount_):
amount(amount_) {}
};
struct balance_pressed {};
Листинг С.7.Конечный автомат банкомата
class atm {
messaging::receiver incoming;
messaging::sender bank;
messaging::sender interface_hardware;
void (atm::*state)();
std::string account;
unsigned withdrawal_amount;
std::string pin;
void process_withdrawal() {
incoming.wait().handle(
[&](withdraw_ok const& msg) {
interface_hardware.send(
issue_money(withdrawal_amount));
bank.send(
withdrawal_processed(account, withdrawal_amount));
state = &atm::done_processing;
}
).handle(
[&](withdraw_denied const& msg) {
interface_hardware.send(display_insufficient_funds());
state = &atm::done_processing;
}
).handle(
[&](cancel_pressed const& msg) {
bank.send(
cancel_withdrawal(account, withdrawal_amount));
interface_hardware.send(
display_withdrawal_cancelled());
state = &atm::done_processing;
}
);
}
void process_balance() {
incoming.wait().handle(
[&](balance const& msg) {
interface_hardware.send(display_balance(msg.amount));
state = &atm::wait_for_action;
}
).handle(
[&](cancel_pressed const& msg) {
state = &atm::done_processing;
}
);
}
void wait_for_action() {
interface_hardware.send(display_withdrawal_options());
incoming.wait().handle(
[&](withdraw_pressed const& msg) {
withdrawal_amount = msg.amount;
bank.send(withdraw(account, msg.amount, incoming));
state = &atm::process_withdrawal;
}
).handle(
[&](balance_pressed const& msg) {
bank.send(get_balance(account, incoming));
state = &atm::process_balance;
}
).handle(
[&](cancel_pressed const& msg) {
state = &atm::done_processing;
}
);
}
void verifying_pin() {
incoming.wait().handle(
[&](pin_verified const& msg) {
state = &atm::wait_for_action;
}
).handle(
[&](pin_incorrect const& msg) {
interface_hardware.send(
display_pin_incorrect_message());
state = &atm::done_processing;
}
).handle(
[&](cancel_pressed const& msg) {
state = &atm::done_processing;
}
);
}
void getting_pin() {
incoming.wait().handle(
[&](digit_pressed const& msg) {
unsigned const pin_length = 4;
pin += msg.digit;
if (pin.length() == pin_length) {
bank.send(verify_pin(account, pin, incoming));
state = &atm::verifying_pin;
}
}
).handle(
[&](clear_last_pressed const& msg) {
if (!pin.empty()) {
pin.pop_back();
}
}
).handle(
[&](cancel_pressed const& msg) {
state = &atm::done_processing;
}
);
}
void waiting_for_card() {
interface_hardware.send(display_enter_card());
incoming.wait().handle(
[&](card_inserted const& msg) {
Интервал:
Закладка: