3.1.1 Synchronous versus Asynchronous Requests

Many functions in the TSPI have the option of operating synchronously or asynchronously. The implementations of such functions have the option to either execute the entire request before the caller's thread is allowed to return from the function call (this is synchronous behavior) or the function implementation can forward the request, for example, to the switch or network, and return from the function call before the request has executed in its entirety (this is asynchonous behavior). When the request later completes, the Service Provider reports the completion by calling a callback procedure originally supplied to it by the TAPI DLL early in the initialization sequence.

To support operations that allow the option of asynchronous execution the TAPI DLL chooses an asynchronous request ID before requesting the operation from the Service Provider. The request ID is passed as a parameter to the operation. Request IDs are positive integers strictly greater than zero, although the Service Provider can make no other assumptions about them. The Service Provider chooses whether to operate sychronously or asynchronously. It reflects its choice back to the TAPI DLL by the value it returns:

Note that the a service provider is free to have a request behave synchronously one time, and asynchronously the next. A practical example of where this may be useful is when information that is normally stored on a server may be cached in the client PC. When a request hits the cache, the request may behave synchronously; otherwise, it may be more appropriate to release the application's thread and execute the request asynchronously.

It is interesting to consider the timing of a "completion" callback relative to when the original request returns. A typical asynchronous request would be implemented by the Service Provider as in the following pseudo-code:


Some_request(Request_ID, ...) {
 check parameters for validity
 check device state for validity
 store Request_ID for Completion Interrupt Handler's use
 manipulate device registers to start physical operation
 return Request_ID  // to indicate asynch operation
}Completion Interrupt Handler: {
 if operation was successful then
   call "completion" callback passing Request_ID and "success"
 else
   call "completion" callback passing Request_ID and "error num"
 endif
}
If the operation completes very rapidly (or the original request returns very slowly) it is possible that the Interrupt Handler that runs when a physical operation completes may be triggered before the original request returns to the application or even the TAPI DLL. This behavior is allowed. The TAPI DLL guarantees that it is prepared to handle an "early" completion callback. Furthermore, it also guarantees that the eventual completion notification to the application will be delivered after the original request returns.