Best practice for asynchronous c api design
I'm about to design a C api for some functionality and I would like to make it asynchronous as the exposed functionality may take some time. Using a blocking api is probably not a good idea as the user of the api will need to make many simultaneous calls.
What is the right way to design the interface so that I can notify the user that the asynchronous operation has completed?
I can think of several different approaches, but I can't say that I am aware of the best practices for this. Does anyone have any experiences with similar API:s?
In this example, the intention is to return an int containing an answer.
Callback function:
typedef void (*callback_function)(int, void *);
/* Calls the callback function with the answer and cookie when done */
error_code DoSomething(callback_function, void *cookie);
Polling:
error_code DoSomething(void *cookie);
/* Blocks until any call has completed, then returns the answer and cookie */
error_code WaitForSomething(int *answer, void **cookie);
Platform specific event queue
/* Windows version, the api calls PostQueuedCompletionStatus when done */
error_code DoSomething( HANDLE hIoCompletionPort,
开发者_运维百科 ULONG_PTR dwCompletionKey,
LPOVERLAPPED lpOverlapped );
Users of this API will typically be event-driven, so designs like the below are probably not going to be a good idea.
Futures:
/* 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);
Platform specific "futures"/events:
/* 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 */
I would go for the callback function as the basic building block. I've seen this design used many times and it works. The void pointer allows you to pass around some context while another callback parameter is generally the error code. You can build other layers on top of this, e.g. a state machine, an event queue or passing OS synchronization objects in the context.
I realize you've asked for a specific scenario, but as far as designing C interfaces go, I've heard immensely positive reviews about this book and usually hear it recommended first to questions similar to yours: C Interfaces and Implementations: Techniques for Creating Reusable Software
精彩评论