Эффективный и современный С++. 42 рекомендации по использованию С++11 и С++14 - [116]
Альтернативный вариант заключается в том, чтобы избежать переменных условия, мьютексов и флагов с помощью вызова >wait
задачей реакции для фьючерса, установленного задачей обнаружения. Это может показаться странной идеей. В конце концов, в разделе 7.4 поясняется, что фьючерс представляет принимающий конец канала связи от вызываемой функции к (обычно асинхронной) вызывающей функции, а между задачами обнаружения и реакции нет отношений “вызываемая-вызывающая”. Однако в разделе 7.4 также отмечается, что канал связи, передающий конец которого представляет собой >std::promise
, а принимающий — фьючерс, может использоваться для большего, чем простой обмен информацией между вызываемой и вызывающей функциями. Такой канал связи может быть использован в любой ситуации, в которой необходима передача информации из одного места вашей программы в другое. В нашем случае мы воспользуемся им для передачи информации от задачи обнаружения задаче реакции, и информация, которую мы будем передавать, — о том, что произошло интересующее нас событие.
Проект прост. Задача обнаружения имеет объект >std::promise
(т.e. передающий конец канала связи), а задача реакции имеет соответствующий фьючерс. Когда задача обнаружения видит, что произошло ожидаемое событие, она устанавливает объект >std::promise
(т.e. выполняет запись в канал связи). Тем временем задача реакции выполняет вызов >wait
своего фьючерса. Этот вызов >wait
блокирует задачу реакции до тех пор, пока не будет установлен объект >std::promise
.
И >std::promise
, и фьючерсы (т.e. >std::future
и >std::shared_ future
) являются шаблонами, требующими параметр типа. Этот параметр указывает тип данных, передаваемый по каналу связи. Однако в нашем случае никакие данные не передаются. Единственное, что представляет интерес для задачи реакции, — что ее фьючерс установлен. Нам нужно указать для шаблонов >std::promise
и фьючерса тип, показывающий, что по каналу связи не будут передаваться никакие данные. Таким типом является >void
. Задача обнаружения, таким образом, будет использовать >std::promise
, а задача реакции — >std::future
или >std::shared_future
. Задача обнаружения устанавливает свой объект >std::promise
, когда происходит интересующее нас событие, а задача реакции ожидает с помощью вызова >wait
своего фьючерса. Даже несмотря на то, что задача реакции не получает никаких данных от задачи обнаружения, канал связи позволит задаче реакции узнать, что задача обнаружения “записала” >void
-данные с помощью вызова >set_value
своего объекта >std::promise
. Так что для данного
>std::promise
код задачи обнаружения тривиален:
>… // Обнаружение события
>p.set_value(); // Сообщение задаче реакции
Код задачи реакции не менее прост:
>… // Подготовка к реакции
>p.get_future().wait(); // Ожидание фьючерса,
> // соответствующего p
>… // Реакция на событие
Этот подход, как и использование флага, не требует мьютексов, работает независимо от того, устанавливает ли задача обнаружения свой объект >std::promise
до того, как задача реакции вызывает >wait
, и невосприимчива к ложным пробуждениям. (Этой проблеме подвержены только переменные условия.) Подобно подходу на основе переменных условия задача реакции оказывается истинно заблокированной после вызова >wait
, так что во время ожидания не потребляет системные ресурсы. Идеально, нет?
Не совсем. Конечно, подход на основе фьючерсов обходит описанные неприятности, но ведь есть и другие. Например, в разделе 7.4 поясняется, что между >std::promise
и фьючерсом находится общее состояние, а общие состояния обычно выделяются динамически. Поэтому следует предполагать, что данное решение приводит к расходам на динамическое выделение и освобождение памяти.
Вероятно, еще более важно то, что >std::promise
может быть установлен только один раз. Канал связи между >std::promise
и фьючерсом является одноразовым механизмом: он не может быть использован многократно. Это существенное отличие от применения переменных условия и флагов, которые могут использоваться для связи много раз. (Переменная условия может быть уведомлена неоднократно, а флаг может сбрасываться и устанавливаться вновь.)
Ограничение однократности не столь тяжкое, как можно подумать. Предположим, что вы хотите создать системный поток в приостановленном состоянии. То есть вы хотели бы заплатить все накладные расходы, связанные с созданием потока, заранее, с тем, чтобы как только вы будете готовы выполнить что-то в этом потоке, вы сможете делать это сразу, без задержки. Или, может быть, вы захотите создать поток в приостановленном состоянии с тем, чтобы можно было настроить его перед выполнением. Такая настройка может включать, например, установку приоритета. API параллельных вычислений С++ не предоставляет способ выполнить такие действия, но объекты >std::thread
предлагают функцию-член >native_handle
, результат которой призван предоставить доступ к API многопоточности используемой платформы (обычно потокам POSIX или Windows). Низкоуровневые API часто позволяют настраивать такие характеристики потоков, как приоритет или сродство.
В этой книге известный автор Скотт Мейерс раскрывает секреты настоящих мастеров, позволяющие добиться максимальной эффективности при работе с библиотекой STL.Во многих книгах описываются возможности STL, но только в этой рассказано о том, как работать с этой библиотекой. Каждый из 50 советов книги подкреплен анализом и убедительными примерами, поэтому читатель не только узнает, как решать ту или иную задачу, но и когда следует выбирать то или иное решение — и почему именно такое.
Когда приходится инкапсулировать, то иногда лучше меньше, чем большеЯ начну со следующего утверждения: Если вы пишете функцию, которая может быть выполнена или как метод класса, или быть внешней по отношению к классу, Вы должны предпочесть ее реализацию без использования метода. Такое решение увеличивает инкапсуляцию класса. Когда Вы думаете об использовании инкапсуляции, Вы должны думать том, чтобы не использовать методы.Удивлены? Читайте дальше.
Java Enterprise Edition (Java EE) остается одной из ведущих технологий и платформ на основе Java. Данная книга представляет собой логичное пошаговое руководство, в котором подробно описаны многие спецификации и эталонные реализации Java EE 7. Работа с ними продемонстрирована на практических примерах. В этом фундаментальном издании также используется новейшая версия инструмента GlassFish, предназначенного для развертывания и администрирования примеров кода. Книга написана ведущим специалистом по обработке запросов на спецификацию Java EE, членом наблюдательного совета организации Java Community Process (JCP)
Эта книга научит вас, как разрабатывать программное обеспечение для платформы J2ME компании «Sun Microsystems». Эта книга придерживается стиля учебного пособия, это не справочное руководство.Цель — дать вам твердую основу в понятиях и техниках, которая даст вам возможность решиться на самостоятельную разработку качественных приложений.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
Это практическое руководство разработчика программного обеспечения на Visual Basic .NET и ADO.NET, предназначенное для создания приложений баз данных на основе WinForms, Web-форм и Web-служб. В книге описываются практические способы решения задач доступа к данным, с которыми сталкиваются разработчики на Visual Basic .NET в своей повседневной деятельности. Книга начинается с основных сведений о создании баз данных, использовании языка структурированных запросов SQL и системы управления базами данных Microsoft SQL Server 2000.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
Embedded system software. General requirements for development and documentationСтандарт подготовлен в развитие ГОСТ Р ИСО/МЭК 12207-99 «Информационная технология. Процессы жизненного цикла программных средств» с целью учета специфики разработки и документирования программного обеспечения встроенных систем реального времени.