Выразите использование аргументов C++ через интерфейсы метода

Я бы порекомендовал либо вариант 1, либо вариант 2. (Отказ от ответственности: я один из основных разработчиков open62541)

  1. Вызов UA_Server_run_iterate из цикла событий libev с помощью waitInternal time, равного 0. Это может означать, что сервер никогда не может спать (опрос open62541 в ev_idle) или что запросы от клиента OPC UA будут иметь дополнительную задержку до 50 мс (максимальное время ожидания по умолчанию open62541).
blockquote>

На данный момент это, вероятно, лучший вариант, который вы могли бы выбрать. Вы можете вызывать UA_Server_run_iterate через фиксированный интервал, например каждые 10 мс, в зависимости от требований приложения. Все остальные опции требуют исправления open62541, и в настоящее время во внутреннем API многое происходит, так как многие функции добавляются в настоящее время. Также обратите внимание на мою заметку в конце!

  1. Патч open62541, позволяющий извлекать файловые дескрипторы, используемые в настоящее время (serverSockets и соединения), сетевым уровнем сервера. Это позволило бы добавить события libev для этих файловых дескрипторов, которые, в свою очередь, могли бы опрашивать UA_Server_run_iterate только при необходимости.
blockquote>

Вероятно, вам не нужно исправлять open62541, поскольку вы можете получить дескриптор файла сокета через сетевой уровень конфигурации сервера, если сетевой уровень является уровнем TCP: server->config.networkLayers[i].serverSockets[j]. Это также может привести к большим объемам работ по техническому обслуживанию, поскольку могут быть разные типы сетевых уровней. Например. pubsub использует UDP, где сокеты хранятся внутри config->pubsubTransportLayers

  1. Реализация пользовательского сетевого уровня сервера, который использует libev. Похоже, это подразумевает некоторое дублирование кода ... Есть ли примеры / учебные пособия для реализации пользовательского сетевого уровня?
blockquote>

Вы можете реализовать свой собственный сетевой уровень, используя интерфейс плагина. напишите свое ( https://github.com/open62541/open62541/blob/master/arch/ua_network_tcp.c ). Поскольку это использует внутренний API, вы можете ожидать много работы по обслуживанию и исправлению патчей. -> Слишком много работы

  1. Запустить цикл событий open62541 в отдельном потоке. Я действительно очень хочу этого избежать, поскольку вся цель системы событий, такой как libev, состоит в том, чтобы избежать проблем, связанных с асинхронной работой. Например, все обратные вызовы из open62541 должны были бы синхронизироваться с основным потоком libev.
blockquote>

Я бы сказал, что это не очень хороший вариант, поскольку вы вводите асинхронные обратные вызовы.


Общее примечание:

В настоящее время у нас есть внутренний черновик и эскиз для доработки сетевого интерфейса, особенно с одним выбором для всех FD сокетов. В настоящее время у нас есть несколько вариантов выбора для нескольких FD.

Также взгляните на следующий PR, где мы уже начали с переделки: https://github.com/open62541/open62541/pull/2271

5
задан driAn 25 January 2009 в 23:05
поделиться

7 ответов

У нашей команды есть подобные конвенции кодирования тем, Вы предлагаете:

1 - аргумент auto_ptr означает, что класс возьмет под свой контроль управление памятью для объекта. (Мы не используем это очень.)

2 - shared_ptr означает, что класс будет, вероятно, использовать аргумент в течение длительного промежутка времени и в особенности может сохранить от его собственного shared_ptr к объекту.

3 - Простая ссылка означает, что аргумент будет только использоваться на время вызова.

Мы рассматриваем это как стандарт кодирования. Это не что-то, что мы документируем для каждого вызова.

6
ответ дан 18 December 2019 в 09:10
поделиться

Я не знаю, существует ли общая идиома, но я действительно знаю, что одним верным способом, которым я предоставляю эту информацию, являются комментарии в интерфейсном заголовке. Пользователи класса будут не всегда читать их, будет не всегда помнить их, и они завинтят их более быстрый, чем можно мигнуть, но информация будет там.

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

Большая проблема со сдерживающими ссылками состоит в том, что Ваши вызывающие стороны никогда не будут помнить, что им не позволяют уничтожить эти вещи, и Вы в конечном счете закончите с 'использованием удаленного объекта' отказы типа.

3
ответ дан 18 December 2019 в 09:10
поделиться

Возможно, я упускаю суть Вас вопрос, но если Ваши прототипы метода в Вашем заголовочном файле будут установкой правильно затем, то это сделает это.
"Неявно" пользователь будет знать, что Ваш данный метод только принимает ссылку на параметр, или что данный параметр только для чтения (константа).. и т.д....

2
ответ дан 18 December 2019 в 09:10
поделиться

В то время как документация является единственным ответом, это - к сожалению, не полезное. Исследование, что я делал шоу, что многие клиенты никогда не читают документацию методов, которые они используют.

Я рекомендовал бы поместить его в номенклатуру Ваших имен методов или имен аргумента, с тех пор по крайней мере, который видим в окне автоматического заполнения. Это ужасно, но это передает сообщение :)

В моем собственном инструменте (для Java/Eclipse) у меня есть тег для того, который позволяет мне объявлять пользователю, когда он должен знать что-то важное относительно параметра.

2
ответ дан 18 December 2019 в 09:10
поделиться

Я не работаю с кодом, который использует повышение или STL, поскольку я не работаю с системами, которые поддерживают их особенно хорошо, но я нашел следующие стандарты полезными...

Я использую ссылки константы и параметры, передаваемые по значению попеременно. (Я использую ссылки, если значения больше, чем регистр - это - просто оптимизация.) Вызываемый сделает копию значением, если ему будет нужен он, таким образом, аргумент может быть немедленно уничтожен. (Случай 3.)

Я использую указатели константы, чтобы указать, что вход ссылкой, и что вызываемый сделает копию ссылкой. Продолжительность жизни аргумента должна превысить продолжительность жизни вызываемого. (Случай 2.)

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

Я не использую ссылки неконстанты сам, просто потому что не очевидно синтаксически в извещателе, что продолжается, но это - просто мой персональный наклон. У меня есть свои причины, но это не означает, что кто-либо еще должен согласиться! Таким образом, можно было бы полезно использовать различие ссылки/указателя для указания на продолжительность жизни, как я описал в случае константы. В этом случае, возможно, указатель = случай 2, и ссылка = случай 3.

Я указываю на случай 1 (вызываемый берет владение) комментарием; это достаточно редко в моем коде, который я не волную по поводу этого слишком много.

2
ответ дан 18 December 2019 в 09:10
поделиться

Я использую следующие префиксы метода для обозначения монопольного использования объекта. Владение подразумевает ответственность за удаление.

Y.take_ZZZ(x)

Вызывающая сторона дает владение x к Y, и вызывающая сторона не должна далее получать доступ x. (потому что Y мог даже сразу удалить x).

Y.own_ZZZ(x)

Подобный для взятия; вызывающая сторона дает владение x к Y, но вызывающая сторона может продолжить ссылаться на x и ожидать, что Y сразу не удалит x (по крайней мере, как длинный, Y существует, и предполагается, что Y будет существовать, по крайней мере, всюду по контексту знания вызывающей стороны Y). Обычно Y не будет удалять x, пока Y не будет уничтожен (хотя Y может передать владение).

Y.know_ZZZ(x)

Вызывающая сторона обеспечивает указатель/ссылку на x (вызывающая сторона может или не может самостоятельно владеть x), но Y не должен брать владение x. Y будет ожидать, что x будет существовать, пока он делает.

x = Y.provide_ZZZ()

x является объектом, которым владеет Y. Y возвращает ссылку (и) объекту, таким образом, вызывающая сторона может 'знать' это. Объект это может быть первоначально нулевой указатель, пока это не требуется, Y, не может создать объект, пока это не необходимо. Выделяется ли x динамично или не скрыт от вызывающей стороны, Y делает то, что необходимо для возврата ссылки на экземпляры объекта, который будет обеспечен. x затем останется инстанцированным, пока Y существует. Иногда я буду, предоставил соответствующему методу Y.done_with_ZZZ(x) так, чтобы вызывающая сторона могла сказать Y, что он сделан, может удалить x.

x = Y.give_ZZZ()

Y оставляет x вызывающей стороне, и не будет никакая дальнейшая ссылка он. Вызывающая сторона будет затем владеть x и будет ответственна за удаление его или предоставление его к другому объекту.

x = Y.lend_ZZZ()

Y обеспечивает ссылку/указатель на x вызывающей стороне (противоположность know_ZZZ) Y сохраняет владение. (подобный для обеспечения, но Y не инстанцирует X, таким образом, он будет или иметь x и возвратит ссылку (указатель), или он не будет и возвращать пустой указатель.

x = Y.check_out_ZZZ() and Y.check_in_ZZZ(x)

С контролем Y предоставляет эксклюзивный доступ вызывающей стороны к x, пока вызывающая сторона не регистрирует его.

x = Y.create_ZZZ()

Y создаст x и сразу оставит его вызывающей стороне (функция фабрики).

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

2
ответ дан 18 December 2019 в 09:10
поделиться

При поиске ясности документация является одним хорошим способом иметь дело с этим. Конечно, это предполагает, что люди обращают внимание на Ваши документы.

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

Если Вы находитесь в среде, где IntelliSense доступен, удостоверьтесь, что необходимая информация присутствует в описании параметра. Это могло сохранить Вас от любого из этих других шагов.

1
ответ дан 18 December 2019 в 09:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: