Как правильно реализовывать IEnumXXX в OPC-сервере?
От: KVakaMarshal Россия  
Дата: 30.04.10 18:59
Оценка:
Приветствую вас уважаемые коллеги. Итак, проблема следующего плана. Пишу свой OPC DA2-сервер (без ATL). Клиентов ранее не писал и с COM'ом не работал. Но в целом все понятно, кроме одного — время жизни перечислителя на стороне OPC-клиента, т.е. когда он должен сделать Release.
Поясню:
Например, OPC-клиент запрашивает перечислитель атрибутов ячеек в группе IOPCGroup::CreateEnumerator(IN REFIID riid,OUT LPUNKNOWN *ppUnk) интерфейса IEnumOPCItemAttributes. У меня два варианта релизации интерфейса:
1. Создаю класс на подобии связанного списка (с внутренними методами типа "AddItem", "GetItem", "DeleteItem" и т.д.), реализую в нем интерфейсы перечислителя, а при вызове клиентом пичкаю этот список всеми существующими ячейками в данной группе. В этом случае объект будет жить сам по себе и уже не будет зависеть от реального набора ячеек в группе. Получается таким образом я делаю некий снимок ячеек группы на момент запроса CreateEnumerator.

2. Создаю агрегатный класс для группы IOPCGroup и реализую методы интерфейса IEnumOPCItemAttributes осуществляющие навигацию уже по существующему списку ячеек в группе. В данном случае перечислитель работает с "живыми" данными и при добавлении/удалении ячеек в группе вызов Next вернет существующие ячейки.

Первый вариант дает преимущество в том, что все используемые в OPC-сервере перечислители можно реализовать одним-двумя шаблонными классами и не париться. А вот во втором случае практически каждый перечислитель надо реализовывать отдельно.

В спецификации (может от невнимательности) не нашел КОГДА должен клиент освобождать перечислитель. Подскажите, как должен вести себя сервер с перечислителями, давать информацию которая имеется на момент запроса (вариант 1) (в данном случае клиент должен получить всю необходимую информацию и освободить объект), или учитывать что клиент, получив перечислитель, может "держать его вечно" (вариант 2)? Кто писал OPC-клиенты, подскажите как вы использовали эти объекты? Есть исходники с набросками OPC-сервера где реализовал первый вариант. Но по логике склоняюсь ко второму варианту.
opc com
Re: Как правильно реализовывать IEnumXXX в OPC-сервере?
От: Vi2 Удмуртия http://www.adem.ru
Дата: 01.05.10 18:07
Оценка:
Здравствуйте, KVakaMarshal, Вы писали:

KVM>... проблема следующего плана. Пишу свой OPC DA2-сервер (без ATL). Клиентов ранее не писал и с COM'ом не работал. Но в целом все понятно, кроме одного — время жизни перечислителя на стороне OPC-клиента, т.е. когда он должен сделать Release.


Я ОРС-сервера не писал, но общий ответ на вопрос "когда OPC-клиент должен сделать Release" такой: клиент должен сделать Release объекту тогда, когда его этот объект больше не интересует. К этому можно добавить, что спецификация интерфейса IEnumXXX не накладывает специальных требований к времени жизни этого объекта. Но, по крайней мере, справедливо, что время его жизни не может превышать время жизни породившей его коллекции, хотя и тут енумератор — это самостоятельный объект.

KVM>Первый вариант дает преимущество в том, что все используемые в OPC-сервере перечислители можно реализовать одним-двумя шаблонными классами и не париться. А вот во втором случае практически каждый перечислитель надо реализовывать отдельно.


Вот и не парься, хотя можешь и попариться.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[2]: Как правильно реализовывать IEnumXXX в OPC-сервере?
От: KVakaMarshal Россия  
Дата: 01.05.10 19:48
Оценка:
Здравствуйте, Vi2, Вы писали:

Vi2>Я ОРС-сервера не писал, но общий ответ на вопрос "когда OPC-клиент должен сделать Release" такой: клиент должен сделать Release объекту тогда, когда его этот объект больше не интересует.


Ну, это понятно, попользовался — освободил. Вот меня и интересует, когда OPC-клиента (я говорю именно о OPC-клиенте и правилах которые регламентирует спецификация, в моем случае OPC DA2.05a) должен прекратить интересовать перечислитель. Я к тому, что возможно вообще нигде не регламентировано что должен OPC-клиент освобождать перечислитель, по схеме "получить перечислитель->прочитать данные->освободить перечислитель". Просто судя по тем чужим наброскам что у меня есть, то это именно так. У меня два пути:
1. Более простая и общая реализация всех перечислителей сервера (а их хватает), естественно с небольшой потерей производительности за счет промежуточного буферизирования. Этот вариант только для той схемы что я описал выше.
2. Более детальная реализация каждого метода интерфейсов IEnumXXX которые используются в OPC. В этом случае больше кода, но выше производительность и полная совместимость с любой схемой "жизни перечислителя".

Ясно, что алгоритмы различных перечислителей, как родных COM'овских, так и OPC'ишных в целом одинаковы. Очень компактно получается их реализовать шаблонно. Все прекрастно понимают гибкость шаблонных классов, поменял в одном месте, изменилось везде. Во втором варианте логика работы методов IEnumXXX:Skip и IEnumXXX:Next будет кардинально отличаться, за чет того что придется работать с разными "живыми данными", кому с группапи, кому с ячейками, а кому и с деревом сигналов. Шаблонным алгоритмом здесь уже не место. Просто если бы я знал что клиент как получит перечислитель сразу считает нужные данные и освободит его, то я сделал бы как в первом варианте, это проще.

Собственно поэтому мне нужен совет не столько по реализации интерфейсов не широкого мира COM, а именно узкой прослойки OPC.

Vi2>Вот и не парься, хотя можешь и попариться.


Ну вот я склоняюсь по своим соображениям и из выше сказанного что попарится надо. Но для уверенности пара советов бывалых OPC'истов мне бы не помешали.
Re[3]: Как правильно реализовывать IEnumXXX в OPC-сервере?
От: KVakaMarshal Россия  
Дата: 03.05.10 11:28
Оценка:
Наконец нашел Sample-исходники сервера OPC DA от OPC Foundation. Оба варианта приемлемы. Правильнее чем в OPC Foundation быть не может. Вопрос снялся. Можно закрыть тему.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.