Виталий Ткаченко - Обратные вызовы в C++

Тут можно читать онлайн Виталий Ткаченко - Обратные вызовы в C++ - бесплатно полную версию книги (целиком) без сокращений. Жанр: comp-programming, издательство Array SelfPub.ru, год 2021. Здесь Вы можете читать полную версию (весь текст) онлайн без регистрации и SMS на сайте лучшей интернет библиотеки ЛибКинг или прочесть краткое содержание (суть), предисловие и аннотацию. Так же сможете купить и скачать торрент в электронном формате fb2, найти и слушать аудиокнигу на русском языке или узнать сколько частей в серии и всего страниц в публикации. Читателям доступно смотреть обложку, картинки, описание и отзывы (комментарии) о произведении.

Виталий Ткаченко - Обратные вызовы в C++ краткое содержание

Обратные вызовы в C++ - описание и краткое содержание, автор Виталий Ткаченко, читайте бесплатно онлайн на сайте электронной библиотеки LibKing.Ru
В практике разработки ПО зачастую встает задача динамической модификации программного кода в зависимости от текущих или настраиваемых значений параметров. Для решения этой задачи широко используются обратные вызовы. В языке C++ обратные вызовы реализуются различными способами, и далеко не всегда очевидно, какой из них лучший для конкретной ситуации. В книге рассмотрены теоретические и практические аспекты организации обратных вызовов, проанализированы достоинства и недостатки различных реализаций, выработаны рекомендации по выбору в зависимости от требований к проектируемому ПО. В первую очередь книга предназначена для программистов среднего (middle) уровня, т.е. тех, кто уже достаточно хорошо знает язык C++, но хотел бы расширить и углубить свои знания в области проектирования и дизайна. В определенной степени она также будет интересна опытным разработчикам, с одной стороны, как систематизация знаний, с другой стороны, как источник идей и методов для решения практических задач.

Обратные вызовы в C++ - читать онлайн бесплатно полную версию (весь текст целиком)

Обратные вызовы в C++ - читать книгу онлайн бесплатно, автор Виталий Ткаченко
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

Отслеживание показаний реализовано в методе, объявленном в строке 10. Поток отслеживания вызывает этот метод, который циклически опрашивает назначенные датчики и в случае превышения пороговых значений осуществляет обратный вызов. Реализация приведена в Листинг 96.

Листинг 96. Отслеживание пороговых значений

void Observer::poll()

{

using namespace std::chrono_literals;

while (!exit_) // (1)

{

std::this_thread::sleep_for(1s); // (2)

std::lock_guard lock(mutex_); // (3)

for (auto& item : containerAlert) // (4)

{

Alert& alert = item.second;

alert.currentTimeout++; // (5)

if (alert.checkTimeout != 0 && alert.currentTimeout >= alert.checkTimeout) // (6)

{

bool triggerAlert = false;

if (alert.alertRule == AlertRule::More) // (7)

{

triggerAlert = alert.sensor->getValue() > alert.alertValue;

}

else // (8)

{

triggerAlert = alert.sensor->getValue() < alert.alertValue;

}

if (triggerAlert) // (9)

{

alert.checkTimeout = alert.callback(item.first, alert.alertValue); // (10)

}

alert.currentTimeout = 0; // (11)

}

}

}

}

В строке 1 объявлен цикл опроса, который выполняется, пока не выставлен индикатор завершения (выставляется в методе stop). В строке 2 поток засыпает на 1 секунду, т. е. интервал опроса равен 1 секунде. В строке 3 блокируется мьютекс, чтобы избежать коллизий добавления/удаления элементов в контейнере.

В строке 4 осуществляется опрос элементов, хранящихся в контейнере. Текущее время опроса в строке 5 увеличивается на единицу. Если уведомление разрешено, о чем говорит ненулевое значение timeout, и время последнего опроса превысило назначенное время (строка 6), то тогда проверяется, имелось ли превышение пороговых значений в соответствии с назначенными правилами (строки 6, 7). Если превышение зафиксировано (строка 9), то осуществляется обратный вызов (строка 10). Этот вызов возвращает следующий интервал опроса, после чего текущее время сбрасывается (строка 11).

6.2.8. Интерфейсный класс

Класс, объявляющий интерфейс для взаимодействия с приложением, представлен в Листинг 97.

Листинг 97. Интерфейсный класс (ControlInterface.h)

namespace sensor

{

class ISensorControl

{

public:

virtual ~ ISensorControl () = default;

virtual void initialize() = 0; // (1)

virtual void shutDown() = 0; // (2)

virtual void assignDriver(DriverPointer driver) = 0; // (3)

virtual DriverPointer getAssignedDriver() = 0; // (4)

virtual DriverPointer getSensorDriver(SensorNumber number) = 0; // (5)

virtual void addSensor(SensorType type, SensorNumber number) = 0; // (6)

virtual void deleteSensor(SensorNumber number) = 0; // (7)

virtual bool isSensorExist(SensorNumber number) = 0; // (8)

virtual bool isSensorOperable(SensorNumber number) = 0; // (9)

virtual SensorValue getSensorValue(SensorNumber number) = 0; // (10)

virtual void querySensorValue(SensorNumber number, SensorValueCallback callback) = 0; // (11)

virtual void readSensorValues(SensorValueCallback callback) = 0; // (12)

virtual SensorValue getMinValue(SensorNumber first, SensorNumber last) = 0; // (13)

virtual SensorValue getMaxValue(SensorNumber first, SensorNumber last) = 0; // (14)

virtual void setAlert(SensorNumber number, SensorAlertCallback callback, SensorValue alertValue, AlertRule alertRule, CheckAlertTimeout checkTimeoutSeс = 1) = 0; // (15)

virtual void resetAlert(SensorNumber number) = 0; // (16)

static ISensorControl* createControl(); // (17)

};

};

В строке 1 и 2 объявлены методы для запуска и останова. В строках 3 и 4 объявлены методы для назначения и получения драйвера. Этот драйвер должен быть создан и назначен в самом начале работы, поскольку он будет передаваться новым создаваемым датчикам. Узнать назначенный драйвер для соответствующего датчика можно в методе 5.

В строках 6 и 7 объявлены методы для добавления и удаления датчика. В методе 8 можно проверить, существует ли датчик с переданным номером, в методе 9 можно проверить, является ли датчик работоспособным.

В строке 10 объявлен метод для чтения текущего показания датчика. В методе 11 осуществляется асинхронный запрос показания датчика, значение будет возвращаться через передаваемый обратный вызов. В строке 12 осуществляется опрос показаний всех работоспособных датчиков, значения также возвращаются через обратный вызов. С помощью методов, объявленных в строках 13 и 14, можно получить минимальное и максимальное значение для набора датчиков с номерами из указанного диапазона.

В строке 15 назначается отслеживание пороговых значений, в строке 16 отслеживание выключается. С помощью метода, объявленного в строке 17, можно создать экземпляр соответствующего интерфейсного класса.

Класс, реализующий интерфейс, приведен в Листинг 98.

Листинг 98 Класс, реализующий интерфейс (SensorControl.h)

namespace sensor

{

class ISensor;

class IDriver;

class CommandQueue;

class AlertControl;

class SensorContainer;

class SensorControl: public ISensorControl

{

public:

SensorControl();

~SensorControl();

void initialize() override;

/* Other Interface methods – they are not displayed here*/

private:

SensorContainer* sensorContainer_; // (1)

CommandQueue* commandQueue_; // (2)

AlertControl* alertControl_; // (3)

bool isInitialized_; // (4)

DriverPointer driver_; // (5)

void checkInitialize(); // (6)

void checkDriver(); // (7)

};

}; //namespace sensor

В строке 1 объявлен контейнер для хранения датчиков, в строке 2 – класс для выполнения асинхронных запросов, в строке 3 – класс для отслеживания пороговых значений. Соответствующие указатели создаются в конструкторе и уничтожаются в деструкторе. Индикатор 4 указывает, была ли выполнена инициализация.

В строке 6 объявлен вспомогательный метод, который проверяет, была ли выполнена инициализация (если нет, выбрасывает исключение). В строке 7 аналогичный метод проверяет, был ли установлен драйвер.

Рассмотрим, как здесь используются обратные вызовы. Для начала самый простой случай – чтение показаний работоспособных датчиков (Листинг 99).

Листинг 99. Обратные вызовы в классе, реализующем интерфейс (SensorControl.cpp)

void SensorControl::readSensorValues(SensorValueCallback callback)

{

checkInitialize(); // (1)

sensorContainer_->forEachSensor([callback](SensorNumber number, SensorPointer sensor) // (2)

{

if (sensor->isOperable()) // (3)

{

callback(number, sensor->getValue()); // (4)

}

}

);

}

В строке 1 производится проверка, инициализирован ли класс. Если класс не проинициализирован, то функция выбросит исключение.

В строке 2 происходит перебор элементов контейнера, в качестве обратного вызова используется лямбда-выражение. Контейнер будет вызывать лямбда-выражение, в которое он будет передавать номер датчика и указатель на экземпляр класса. В теле выражения проверяется, является ли датчик работоспособным (строка 3), и если да, то выполняется соответствующий обратный вызов (строка 4).

Рассмотрим теперь поиск максимального и минимального значения для заданного диапазона номеров датчиков. Вначале разработаем вспомогательный класс, который будет последовательно принимать на вход показания датчиков и искать среди них максимальное и минимальное значение (Листинг 100).

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать


Виталий Ткаченко читать все книги автора по порядку

Виталий Ткаченко - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки LibKing.




Обратные вызовы в C++ отзывы


Отзывы читателей о книге Обратные вызовы в C++, автор: Виталий Ткаченко. Читайте комментарии и мнения людей о произведении.


Понравилась книга? Поделитесь впечатлениями - оставьте Ваш отзыв или расскажите друзьям

Напишите свой комментарий
x