Дело в том, как создать нечто общее между средой и объектами обработки. Я поэкспериментировал с диспетчером TCP, использующим boost.asio, но попытка создать что-то общее кажется кошмаром :). Кто-нибудь пытался сделать что-то подобное? Как лучше всего это сделать?
Я не использовал Boost, но я обычно решал проблему такого рода, создавая базовый класс Device, с которым взаимодействует сервер, а затем делил его на подклассы для каждого типа устройства и заставлял подклассы работать с устройством. нечетность. Таким образом, класс Device становится определением вашего протокола. Кроме того, класс Device должен быть переносимым, а подклассы - нет.
Если вам нужно было стать более изощренным, вы можете использовать шаблон Factory для создания реальных подклассов объектов.
Что касается реального общения, я бы посмотрел, смогу ли я просто запустить один процесс на устройство. Если вам нужно иметь более одного Устройства на процесс, в Linux я бы просто использовал select()
и его друзей для управления вводом / выводом между различными экземплярами Устройства. Я не знаю, как это сделать в Windows; select
работает только для сокетов, а не для последовательных портов или других файловых вещей.
Другие вещи, которые приходят на ум, могут оказаться полезными, в том числе dbus и библиотека MPI (Message Passing Interface), хотя они не являются полными решениями вашей проблемы (dbus не осуществляет межкомпьютерные коммуникации, IIRC).
Помогает ли это вообще?
РЕДАКТИРОВАТЬ: Требуется отформатированный ответ на ответ Тома ...
Содержит ли ваш класс устройств специфичные для связи части? Потому что это то, чего я хотел избежать.
Подклассы содержат специфичные для связи части. Вот и весь смысл использования здесь подклассов; универсальный материал входит в базовый класс, а специфика - в подкласс.
Я думал о чем-то вроде этого: скажем, есть диспетчер, специфичный для используемого носителя, который создает объект Connection для каждого соединения (специфичный для носителя), Device obj. будет также создан, но только общий, и Соединение будет передавать входящие данные на Устройство, и Устройство будет передавать ответы обратно Соединению.
Я думаю, что это может быть немного сложно, и вы ожидаете, что универсальное устройство будет иметь дело с определенным соединением, которое может быть сложно поддерживать быстро.
То, что я бы порекомендовал, это подкласс Device специально для обработки этого типа Соединения, которое берет Соединение от диспетчера и владеет им до тех пор, пока соединение не закроется. Тогда ваш менеджер может общаться с общим устройством, а соединение может связываться со спецификой.
Пример: скажем, у вас есть датчик температуры USB штуковина. У вас есть диспетчер, который ловит сигнал «USB вещь подключена». Когда он видит, что USB-устройство подключено:
- Диспетчер создает
USBTemperatureThingConnection
.
- Диспетчер создает
USBTemperatureDevice
, который является подклассом устройства, давая USBTemperatureThingConnection
USBTemperatureDevice
в качестве параметра конструктора.
USBTemperatureDevice::USBTemperatureDevice(USBTemperatureThingConnection* conn)
идет и устанавливает все, что ему нужно локально, чтобы завершить настройку Соединения, затем отправляет сообщение Диспетчеру устройств, сообщающее, что оно настроило себя.
Некоторое время спустя диспетчер устройств хочет установить время на всех устройствах. Таким образом, он перебирает свой список устройств и вызывает общий (возможно, даже абстрактный) метод Device::SetTime(const struct timespec_t&)
для каждого из них.
Когда он достигает вашего температурного устройства, он вызывает USBTemperatureDevice::SetTime(const struct timespec_t&)
, так как USBTemperatureDevice
переопределяет значение в Device
(которое было либо абстрактным, то есть virtual void SetTime(const struct timespec_t&) = 0;
, либо неактивным, то есть virtual void SetTime(const struct timespec_t&) {}
, поэтому вам не нужно переопределять его для устройств, которые не могут установить время). USBTemperatureDevice::SetTime(const struct timespec_t&)
делает все, что нужно для датчика температуры USB, используя USBTemperatureThingConnection
, чтобы установить время.
Некоторое время спустя устройство может отправить обратно сообщение «Результат установки времени», сообщающее, работает ли оно или нет.Это приходит на USBTemperatureThingConnection
, который пробуждает вашу нить, и вам нужно с этим справиться.Таким образом, ваш метод USBTemperatureDevice::DealWithMessageFromSensor()
(который существует только в USBTemperatureDevice
) погружается в содержимое сообщения и выясняет, работает ли установка времени или нет.Затем он принимает этот результат, превращает его в значение, определенное в enum Device::ResultCode
, и вызывает Device::TimeSetComplete(ResultCode result)
, который записывает результат, устанавливает флаг (bool Device::timeComplete
), говорящий о том, что результат находится в, а затем нажимает Semaphore
или Condition
, чтобы разбудить Диспетчер устройств и заставить его проверить все Device
, в случае, если он был заблокирован, ожидая, пока все устройства завершат установку времени, прежде чем продолжить.
Я понятия не имею, что этокартина называется.Если бы я нажал, я бы сказал «подклассы» или «объектно-ориентированный дизайн», если бы я чувствовал раздражение.«Промежуточное программное обеспечение» - это класс Device
, DeviceManager и все их подчиненные.Затем приложение просто обращается к диспетчеру устройств или, самое большее, к общему интерфейсу Device
определенного устройства.
Кстати.План фабрики был запланирован, каждый объект работал бы в отдельном потоке:)
Приятно слышать.