Synchronous versus Asynchronous Requests

Some TSPI functions operate synchronously, while others operate asynchronously. Synchronous functions execute the entire request before the caller's thread is allowed to return from the function call. Asynchronous functions return from the function call before the request has executed in its entirety. When the asynchronous request later completes, the service provider reports the completion by calling a callback procedure originally supplied to it by tapi32.dll early in the initialization sequence.

To support asynchronous functions, tapi32.dll passes an asynchronous request identifier to the service provider as part of the function call. Request identifiers are positive integers strictly greater than zero. The service provider does whatever is required to start the operation and then returns the request identifier to tapi32.dll. When the asychronous operation eventually completes, the service provider reports completion by calling a special callback procedure (ASYNC_COMPLETION) in tapi32.dll. The parameters to this procedure are the original request identifier and the result code. Result values are 0 for success and negative values for error indications.

For synchronous functions, the service provider simply runs the entire operation to completion. If the operation succeeds, it returns zero. If an error occurs, it returns a negative error number. TAPI does not pass a request identifier to synchronous functions.

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 pseudocode:

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
}
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 tapi32.dll. This behavior is allowed. The tapi32.dll guarantees that the eventual completion notification to the application is delivered after the original request returns.