API calls that may take a significant amount of time to complete (MgslTransmit, MgslReceive, MgslWaitEvent, MgslGetTraceEvent) require that the application pass an application allocated OVERLAPPED structure to the API. Initialize the hEvent member of the overlapped structure with the handle of a WIN32 manual reset event allocated with CreateEvent. Set the other members of the overlapped structure to zero. If the API returns ERROR_IO_PENDING, monitor the event with the WIN32 functions WaitForSingleObject or WaitForMultipleObjects. When the API signals the event object, the call is complete and returned information is valid.
For more information about the OVERLAPPED structure, WIN32 events, and synchronization refer to the WIN32 SDK documentation.
Implement polling by calling WaitForSingleObject with a time-out of 0, which returns immediately with the state of the event object. Implement blocking by setting the time-out to the macro INFINITE, causing WaitForSingleObject to return only after the API call has completed. Pass a finite time-out to block until completion or the expiration of the time-out.
The API calls that use asynchronous notification can have only one pending instance of each API call. For example, if a MgslTransmit call is pending, the application cannot call MgslTransmit again until the original call completes. Different API calls, such as MgslTransmit and MgslReceive, may be simultaneously pending. Calling an API function that uses asynchronous notification while an instance of that API call is already pending, results in a return code of ERROR_BUSY.
When calling API routines which may not complete immediately (MgslTransmit, MgslReceive, MgslWaitEvent, and/or MgslGetTraceEvent), it is imperative that you not make a call to the same routine passing the same OVERLAPPED structure and event object handle if the prior call returns ERROR_IO_PENDING.
Every API call will either complete immediately, or at a later time. If the call returns ERROR_IO_PENDING, the call will complete as some later time. If the call can process the request immediately, the call completes synchronously, in a timely fashion, returning to the application.
Thus, if a call previously returned ERROR_IO_PENDING, and the application erroneously makes the same call, passing the same OVERLAPPED structure and event object handle, the API will determine that an identical call is already in progress. As the call completes immediately, with an ERROR_BUSY status, the event object will be signaled, indicating the call has completed.
In this case, the second call completed with an error, and the first call is still pending. But, the event object has been signalled, which could cause the application to believe the first operation was completed.