Symbian
Symbian Developer Library

SYMBIAN OS V9.4

Feedback

[Index] [Previous] [Next]


How to handle multiple asynchronous requests with a wait loop

A user thread which requires asynchronous services from more than one asynchronous service provider uses a wait loop.

The allows a thread to issue as many request as are necessary and to handle their completion. This construction forms the heart of almost all programs that run under Symbian OS.

A typical program:

As an example, a terminal emulator must work with multiple requests simultaneously, to deal with:

[Top]


Typical wait loop protocol

The typical protocol of a wait loop is:

initialize;
while (!finished())
    {
    wait for one or more requests to complete
    decide which request completed, and handle it
    }
terminate;

Note that only one request should be handled per iteration of the loop. As part of the request completion handling process, the request may be re-issued, or new requests issued or existing ones cancelled. If the request cannot be identified, then the thread’s request semaphore has been signalled invalidly; this is indicative of a programming error, a condition is known as a stray signal - the wait loop should raise a panic.

[Top]


Multiple outstanding requests

In the case of a terminal emulator which works with multiple outstanding requests, it must be able to service whichever request completes and must be able to re-issue a request, if necessary. For example, when one key has been processed, a request for the next key must be issued.

In the following example:

class TerminalEmulator
    {
public:
    void MainLoop(); // main loop
private:
    void Initialize(); // initialize
    void Terminate(); // clean up and terminate
    TBool IsFinished(); // whether finished
private:
    // request status objects
    TRequestStatus iKeyPressed; // whether key pressed
    ...                         // ...etc for other request status
    // handler functions
    void HandleKeyPressed();    // handle key pressed
    ...                         // ... etc other handlers
    ...
    };
void TerminalEmulator::MainLoop()
    {
    Initialize();         // Initialize emulator
    while (!IsFinished()) // Handle events until finished
        {
        // wait for any request to complete
        User::WaitForAnyRequest();

        // identify and handle the completed request
        if (iKeyPressed!=KRequestPending)
            {
            HandleKeyPressed();
            }
        else if (iReceiveCompleted!=KRequestPending)
                {
                HandleReceiveCompleted();
                }
            else if (iTransmitCompleted!=KRequestPending)
                    {
                    HandleTransmitCompleted();
                    }
                else
                    {
                    // something we werent expecting
                    // panic !
                    }
        }
    }

Note