Лучшие практики для асинхронного проектирования c api - PullRequest
3 голосов
/ 26 января 2011

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

Как правильно спроектировать интерфейс, чтобы я мог уведомить пользователя о завершении асинхронной операции?

Я могу придумать несколько разных подходов, но не могу сказать, что мне известны лучшие практики для этого. У кого-нибудь есть опыт работы с подобным API: s?

В этом примере мы хотим вернуть int, содержащий ответ.

Функция обратного вызова:

typedef void (*callback_function)(int, void *);

/* Calls the callback function with the answer and cookie when done */
error_code DoSomething(callback_function, void *cookie);

Опрос:

error_code DoSomething(void *cookie);

/* Blocks until any call has completed, then returns the answer and cookie */
error_code WaitForSomething(int *answer, void **cookie);

Очередь событий для конкретной платформы

/* Windows version, the api calls PostQueuedCompletionStatus when done */
error_code DoSomething( HANDLE hIoCompletionPort,
                        ULONG_PTR dwCompletionKey,
                        LPOVERLAPPED lpOverlapped );

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

Фьючерс:

/* External dummy definition for a future */
struct Future_Impl {
    int unused;
};
typedef Future_Impl *Future;

/* Initializes a future, so that it can be waited on later */
error_code DoSomething(Future *future);

/* Blocks until the result is available */
error_code WaitForSomething(Future future, int *answer);

«Фьючерсы» / события, специфичные для платформы:

/* Windows version, the api signals the event when done */
error_code DoSomething( HANDLE hEvent, int *answer );

/* Can be waited on using WaitForMultipleObjects,
   but that has a limit on how many events that can be used */

Ответы [ 2 ]

2 голосов
/ 26 января 2011

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

0 голосов
/ 26 января 2011

Я понимаю, что вы спрашивали о конкретном сценарии, но что касается разработки интерфейсов C, я слышал очень положительные отзывы об этой книге и обычно слышал, что ее рекомендуют в первую очередь к вопросам, аналогичным вашим: Интерфейсы Cи внедрения: методы создания программного обеспечения многократного использования

...