Обратные вызовы в C++ - [45]
>class CommandQueue
>{
>public:
> void start(); // (1)
> void stop(); // (2)
> void addCommand(SensorNumber number, SensorPointer pointer, SensorValueCallback callback); // (3)
>private:
> struct Command // (4)
> {
> SensorNumber number;
> SensorPointer pointer;
> SensorValueCallback callback;
> };
> std::queue
> std::condition_variable conditional_; // (6)
> std::mutex mutex_; // (7)
> std::thread queueThread_; // (8)
> bool exit_; // (9)
> void readCommand(); // (10)
>};
В строке 4 объявлена структура, в которой будут храниться данные для выполнения вызова: номер датчика, указатель на класс датчика и объект вызова. В строке 5 объявлен контейнер, который будет хранить указанные структуры. В строках 6 и 7 объявлены переменные для синхронизации операций записи/чтения очереди, в строке 8 объявлен класс для запуска потока обработки очереди, в строке 9 объявлен индикатор для завершения работы потока.
В строке 1 объявлен метод, который запускает поток обработки очереди, в строке 2 объявлен метод для остановки этого потока. Метод, объявленный в строке 3, добавляет переданные данные в очередь путем создания экземпляра структуры 4 и размещения ее в контейнере 5.
Обработка очереди реализована в методе, объявленном в строке 10. Поток обработки очереди вызывает этот метод, который, в свою очередь, ожидает поступления записей и обрабатывает их. Реализация приведена в Листинг 95.
>void CommandQueue::readCommand()
>{
> while (!exit_) // (1)
> {
> std::unique_lock
> conditional_.wait(lock, [this]() {return commandQueue_.size() > 0 || exit_ == true; }); // (3)
> while (commandQueue_.size() > 0 && exit_ == false) // (4)
> {
> Command cmd = commandQueue_.front(); // (5)
> commandQueue_.pop(); // (6)
> lock.unlock(); // (7)
> cmd.callback(cmd.number, cmd.pointer->getValue()); // (8)
> lock.lock(); // (9)
> }
> }
>}
Пока не установлен индикатор завершения (устанавливается в методе stop), выполняется цикл 1. Вначале блокируется мьютекс 2 (это необходимо для корректной работы условной переменной), затем осуществляется ожидание условной переменной 3. Когда метод addCommand сформировал новую запись и добавил ее в контейнер, он инициирует срабатывание условной переменной, и поток выполнения переходит к циклу 4 (мьютекс при этом оказывается заблокирован). Этот цикл работает, пока очередь не опустеет либо будет установлен индикатор выхода.
В строке 5 из контейнера извлекается очередная запись, в строке 6 эта запись удаляется из контейнера. В строке 7 снимается блокировка мьютекса, что позволяет добавлять в контейнер новые записи, пока идет обработка очередной команды. В строке 8 осуществляется обратный вызов, в строке 9 мьютекс блокируется вновь, и далее повторяется цикл 4.
6.2.7. Наблюдатель
Объявление класса наблюдателя приведено в Листинг 95.
>class Observer
>{
>public:
> void start(); // (1)
> void stop(); // (2)
> void addAlert(SensorNumber number, SensorPointer pointer, SensorAlertCallback callback, SensorValue alertValue, AlertRule alertRule, CheckAlertTimeout checkTimeoutSeс); // (3)
> void deleteAlert(SensorNumber number); // (4)
>private:
> struct Alert // (5)
> {
> Alert() {}
> Alert(SensorAlertCallback callback, SensorValue alertValue, AlertRule alertRule, SensorPointer sensor, CheckAlertTimeout checkTimeout):
> callback(callback), alertValue(alertValue), alertRule(alertRule), sensor(sensor), checkTimeout(checkTimeout), currentTimeout(0)
> {
> }
> SensorAlertCallback callback;
> SensorValue alertValue;
> AlertRule alertRule;
> SensorPointer sensor;
> CheckAlertTimeout checkTimeout;
> CheckAlertTimeout currentTimeout;
> };
> std::map
> std::thread pollThread_; // (7)
> bool exit_; // (8)
> std::mutex mutex_; // (9)
> void poll(); // (10)
>};
В строке 1 объявлен метод для запуска процесса отслеживания пороговых значений, в строке 2 – метод для останова. Метод в строке 3 добавляет датчик для отслеживания, метод 4 – удаляет.
В строке 5 объявлена структура, в которой хранятся данные, необходимые для отслеживания показаний датчика. В строке 6 объявлен контейнер для хранения указанных структур; метод addAlert добавляет запись в контейнер, метод deleteAlert удаляет ее. В строке 7 объявлен класс для запуска потока для отслеживания, в строке 8 объявлен индикатор выхода, в строке 9 объявлен мьютекс для синхронизации.
Отслеживание показаний реализовано в методе, объявленном в строке 10. Поток отслеживания вызывает этот метод, который циклически опрашивает назначенные датчики и в случае превышения пороговых значений осуществляет обратный вызов. Реализация приведена в Листинг 96.
![Изучаем Java EE 7](/storage/book-covers/e0/e0ee9b7e3e4f168a93df98d7e47d66089eac3652.jpg)
Java Enterprise Edition (Java EE) остается одной из ведущих технологий и платформ на основе Java. Данная книга представляет собой логичное пошаговое руководство, в котором подробно описаны многие спецификации и эталонные реализации Java EE 7. Работа с ними продемонстрирована на практических примерах. В этом фундаментальном издании также используется новейшая версия инструмента GlassFish, предназначенного для развертывания и администрирования примеров кода. Книга написана ведущим специалистом по обработке запросов на спецификацию Java EE, членом наблюдательного совета организации Java Community Process (JCP)
![Геймдизайн. Рецепты успеха лучших компьютерных игр от Super Mario и Doom до Assassin’s Creed и дальше](/storage/book-covers/d0/d0fc13172d4310c9da7b10ba57a3fcb2e3d9f10d.jpg)
Что такое ГЕЙМДИЗАЙН? Это не код, графика или звук. Это не создание персонажей или раскрашивание игрового поля. Геймдизайн – это симулятор мечты, набор правил, благодаря которым игра оживает. Как создать игру, которую полюбят, от которой не смогут оторваться? Знаменитый геймдизайнер Тайнан Сильвестр на примере кейсов из самых популярных игр рассказывает как объединить эмоции и впечатления, игровую механику и мотивацию игроков. Познакомитесь с принципами дизайна, которыми пользуются ведущие студии мира! Создайте игровую механику, вызывающую эмоции и обеспечивающую разнообразие.
![Обработка событий в С++](/build/oblozhka.dc6e36b8.jpg)
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
![MFC и OpenGL](/build/oblozhka.dc6e36b8.jpg)
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
![Симуляция частичной специализации](/storage/book-covers/7e/7e33d937f206a76edb7f45006e896cc191605df5.jpg)
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
![Питон — модули, пакеты, классы, экземпляры](/build/oblozhka.dc6e36b8.jpg)
Python - объектно-ориентированный язык сверхвысокого уровня. Python, в отличии от Java, не требует исключительно объектной ориентированности, но классы в Python так просто изучить и так удобно использовать, что даже новые и неискушенные пользователи быстро переходят на ОО-подход.