LINUX.ORG.RU

Функции с переменным числом аргументов: va_arg vs void*

 


0

2

Пытаюсь выбрать наиболее подходящий вариант. Речь идёт о тех случаях, когда количество и тип переменных заранее известно, но вызов должен происходить через некий интерфейс, как, например, через syscall. Фактически, я сейчас пытаюсь определиться между двумя вариантами:

int api1( unsigned int id, ... );
int api2( unsigned int id, const void* arg );

В случае api1 предполагается передавать набор аргументов в зависимости от id.

В случае api2 предполагается передавать указатель на некую структуру, которая будет отличаться в зависимости от id и в которой будет виден весь список аргументов.

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

А какой вариант предпочли бы вы? Или может существуют ещё способы?

★★★
Ответ на: комментарий от u5er

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

А и нет одного удобного обмена сообщениями между процессами и внутри процессов. Поэтому, их всё придумывают и придумывают, и пишут и пишут…

Vic
()
Ответ на: комментарий от u5er

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

Ох…

Очевидно, что эти наборы будут полностью отличаться друг от друга, т.к. выполняют абсолютно разные задачи.

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

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

aiqu6Ait ★★★★
()
Ответ на: комментарий от Vic

Не проще сразу придумать асинхронный RPC, который по сути обмен сообщениями

Можут и проще, но зачем, когда у меня уже есть очереди сообщений, который и есть по сути обмен сообщениями? А если мне нужен двухсторонний обмен, то нужна уже пара очередей.

Знаешь сигналы POSIX? От одной мысли о них мне становится грустно и тоскливо: в них нельзя передать никакую дополнительную информацию, они сбивают вызовы (EINTR) и т.д.. Вот мне нужно что-то подобное, только синхронное, с возможностью передачи аргументов и возврата результата и возможностью работать параллельно с серверным кодом. Как раз то, что у меня и получилось.

Фишка в том, что вызов RPC работает в отдельном потоке (ну или делает вид, что в отдельном). Если бы я делал подобный фуцнкционал на сообщениях, то мне всё равно бы пришлось делать отдельный поток, который принимает, обрабатывает, и отвечает на сообщения. В том числе и от нескольких клиентов одновременно.

кроме опасности принципа калбэка

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

Сервера же пишут для однотипной обработки RPC запросов от множества клиентов и там время передачи и загруженность сервера будет иметь значение.

Зависит от задачи. Одно дело - это условный hi-load вебсервер, который обслуживает какой-нибудь крупный сайт, а другое дело - это условный mpd, который обслуживает один, максимум два клиента и редкими запросами. В любом случае, не думаю, что для большой нагрузки RPC будет эффективен: слишком много накладных расходов.

u5er ★★★
() автор топика
Ответ на: комментарий от aiqu6Ait

Я могу посоветовать тебе стоит прописать непротиворечивые верифицируемые требования для своей задачи - что ты должен делать в каждом случае

У меня-то они уже не только прописаны, но и реализованы. Судя по твоему посту, проблема в том, что я не умею излагать свои мысли так, чтоб они были понятны для читающего :( Тут уже мои полномочия всё.

u5er ★★★
() автор топика
Ответ на: комментарий от u5er

функций может быть довольно много, тогда массив получится довольно большим.

Так ведь switch/case вам всё равно его сделает, но это писать - большее захламление исходника.

vodz ★★★★★
()
Ответ на: комментарий от u5er

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

deep-purple ★★★★★
()
Ответ на: комментарий от vodz

Не согласен. Если id идут по порядку, то можно объявить массив указателей на функции и код будет примерно таким

int callHandler( uint32_t id, const void* arg ){
	
	if( id > MAX_ID ) return -1;
	return callHandlers[id].handler( arg );
}
u5er ★★★
() автор топика
Ответ на: комментарий от u5er

проблема в том, что я не умею излагать свои мысли так, чтоб они были понятны для читающего :(

не расстраивайся, может все в порядке. я ведь тему по диагонали прочитал.

aiqu6Ait ★★★★
()