crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

 
Ответить в данную темуНачать новую тему
> Доступ к железу в многопоточном приложении
r_13
  опции профиля:
сообщение 17.1.2012, 14:10
Сообщение #1


Новичок


Группа: Новичок
Сообщений: 3
Регистрация: 13.9.2011
Пользователь №: 2870

Спасибо сказали: 0 раз(а)




Репутация:   0  


Добрый день,
есть многомодульная программа с кучей потоков (threads) и есть железо, которое подключается по USB. Один из модулей ловит сообщения от USB и создает\удаляет объекты класса Device, который предоставляет доступ к железу. Куча других классов из разных модулей получает указатели на объекты этого класса по запросу и манипулируют с ними. Если происходит USB disconnect, то модуль, что раздает указатели на Device, посылает соответствующее сообщение. Но поскольку система многопоточная, то сообщение может прийти позже, чем будет попытка обращения к недоступному более железу.
Ясно, что надо синхронизировать через mutex (что и делается), но количество объектов, желающих общаться с железом растет и учесть все варианты становится все сложнее. Может есть какой-нибудь design pattern для этого? Может это не правильно раздавать всем подряд указатели? Нужен какой-нибудь режим регистрации тех, кто получает указатель? Задача то довольно стандартная для околожелезячных прог. Наверняка есть "стандартное" решение\подход...
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Влад
  опции профиля:
сообщение 17.1.2012, 14:29
Сообщение #2


Участник
**

Группа: Участник
Сообщений: 146
Регистрация: 20.3.2009
Из: Санкт-Петербург
Пользователь №: 627

Спасибо сказали: 46 раз(а)




Репутация:   8  


Мне кажется, что это неправильно, что один модуль раздает другим указатели, и эти другие - делают, что хотят и когда хотят..... в том числе, могут обращаться к недоступному больше железу.

Лично я бы сделал бы несколько иначе а врхитектурном плане:
Один модуль ловит сообщения от USB _и_ общается с железом. Он предоставляет всем остальным модулям доступ к железу посредством доступа к _своему интерфейсу_, не предоставляя этим "остальным модулям" прямого доступа к железу. Запросы сторонних модулей могут ставиться в очередь и обрабатываться по логике, определяемой этим "железячным" модулем. Таким образом, все взаимодействие с конкретной USB-железякой инкапсулировано внутри этого модуля. Если железяка отключается, то этот модуль просто завершает все оставшиеся в очереди запросы неуспешно. Нет?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
r_13
  опции профиля:
сообщение 17.1.2012, 16:09
Сообщение #3


Новичок


Группа: Новичок
Сообщений: 3
Регистрация: 13.9.2011
Пользователь №: 2870

Спасибо сказали: 0 раз(а)




Репутация:   0  


Да, так пожалуй безопаснее, хотя одновременный доступ будет только к одной железяке. Впрочем можно и Thread Pool сделать (по одному потоку на железяку) и тогда они между собой общаться смогут. И запросы придется с блокировкой делать, если, скажем надо значение из регистра получить. Для общения с внешними модулями этот вариант наверно стоит попробовать. Но и внутри модуля куча классов, которые получают IHwAccess и работают с ним (доступ к отдельным частям железа и платам расширения). Их запросы через очередь наверно не получится. Иначе придется еще транзакции вводить. Да и таймауты могут появиться.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Iron Bug
  опции профиля:
сообщение 17.1.2012, 17:55
Сообщение #4


Профессионал
*****

Группа: Модератор
Сообщений: 1587
Регистрация: 6.2.2009
Из: Yekaterinburg
Пользователь №: 533

Спасибо сказали: 218 раз(а)




Репутация:   12  


для каждой железки делается один поток на всё приложение. он буферизует и отправляет сообщения, а также занимается приёмом. а потом уже асинхронно раздаёт ответы ожидающим.
это единственное нормальное решение при обращении к железу без конкуренции запросов.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Влад
  опции профиля:
сообщение 18.1.2012, 9:27
Сообщение #5


Участник
**

Группа: Участник
Сообщений: 146
Регистрация: 20.3.2009
Из: Санкт-Петербург
Пользователь №: 627

Спасибо сказали: 46 раз(а)




Репутация:   8  


r_13, мне вот как раз несколько (эххх.... изрядно уж!) лет назад приходилось разрабатывать похожую систему..... Несколько (много) "железных" устройств общались с компами по COM-портам и еще взаимодействовали друг с другом при этом.
Архитектура получилась следующая:
- на каждый тип "железного" устройства конструируется свой класс. Все эти "железячные" классы наследуют и поддерживают единый общий интерфейс (наследуются от абстрактного класса). Внутри класса для общения с устройством через COM-порт создаются два потока: на прием и на передачу, и две очереди: принятых сообщений и сообщений на отправку. Класс сам отслеживает таймауты, состояние устройства и прочее....
- количество экземпляров нужного класса определяется количеством железок данного типа, подключенных по каналам связи (у меня читалось из конфиг файла).
- для организации взаимодействия устройств друг с другом сконструирован еще один класс - условно, диспетчер. Диспетчер создает (читая из конфига) нужное число экземпляров конкретных классов.
- взаимодействие экземпляров между собой (как экземпляров одного класса, так и разных классов) идет по схеме "поставщик сообщений - подписчики". Все сообщения, принятые от конкретной железки, экземпляр соответствующего класса отдает диспетчеру. А диспетчер ведет реестр (список, лист) подписчиков, и отдает им сообщения. Здесь получается топология типа "звезда". Подписчик указывает, сообщения какого типа (а они разных типов) он желает получать. Каждый подписчик сам решает, как обрабатывать полученные сообщения. Прямого взаимодействия между железячными экземплярами нет, все идет только и исключительно через диспетчер.
- в одном компе - один диспетчер и несколько "железячных" экземпляров. А диспетчеры разных компов общаются по Ethernet по такой же схеме - на одном компе поднимается "сервер", по сути дела - диспетчер более высокого уровня. Здесь тоже топология "звезда".
Вот как-то так.....

Сообщение отредактировал Влад - 18.1.2012, 9:29
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Iron Bug
  опции профиля:
сообщение 18.1.2012, 17:43
Сообщение #6


Профессионал
*****

Группа: Модератор
Сообщений: 1587
Регистрация: 6.2.2009
Из: Yekaterinburg
Пользователь №: 533

Спасибо сказали: 218 раз(а)




Репутация:   12  


Цитата(Влад @ 18.1.2012, 12:27) *
Архитектура получилась следующая:

у меня получилось нечто подобное, но только взаимодействие было через очереди, а диспетчер координировал подключение процессов к очередям (там было межпроцессное взаимодействие), выдавая процессам координаты нужной очереди по условному имени девайса.
в общем, вполне нормальная архитектура, если девайсы последовательные. с асинхронными всё намного сложнее.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
r_13
  опции профиля:
сообщение 18.1.2012, 19:24
Сообщение #7


Новичок


Группа: Новичок
Сообщений: 3
Регистрация: 13.9.2011
Пользователь №: 2870

Спасибо сказали: 0 раз(а)




Репутация:   0  


Здесь по классу на девайс и интерфейс тоже есть. Только вместо очередей или сообщений был сделан просто геттер, возвращающий map с идентификаторами и указателями на девайс (интерфейс). Это, видимо, и надо переделать. Всем спасибо.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 18.10.2019, 21:39