Asynchronous Functions
You can identify an asynchronous function on Symbian OS by its inclusion of an argument of type TRequestStatus. TRequestStatus is a type class (which encapsulates a simple integer) that represents the status of the asynchronous function - that is, whether the function is in progress or has finished and, if it has finished, what its final status is. Many of the Symbian OS API functions come in both synchronous and asynchronous versions.
As an example, consider a traditional synchronous function called MyFunc():
TInt MyFunc(TAny *aSomeArg);
This function returns after it is completely finished and the return value indicates the status of the function.
An asynchronous version of MyFunc() would look like:
void MyFunc(TAny *aSomeArg, TRequestStatus& aStatus);
This function may perform the same functionality as the synchronous version, but instead of returning when it is completed, the function returns immediately with aStatus set to KRequestPending to indicate that MyFunc() is executing in parallel with the calling thread. When the asynchronous function completes, aStatus changes to the function's final status (KErrNone if successful).
At some point you will need to know when the asynchronous function has completed. You could wait for the function to complete as follows:
TRequestStatus status; MyFunc(anArg, status);
// Code may be here which executes in parallel to MyFunc() while (status == KRequestPending) ;
but polling the TRequestStatus variable like this is clearly wasteful of processor cycles. A more efficient option is to use User::WaitFor Request(TRequestStatus& aStatus), which will block your calling thread until the asynchronous function has completed (the name WaitForRequest means that it is waiting for the asynchronous request to complete), but your thread will yield control to other threads while it is waiting. For example:
TRequestStatus status; MyFunc(someArg, status); User::WaitForRequest(status);
// MyFunc() is complete, status now contains the function status
User::WaitForRequest() waits at a special semaphore owned by the calling thread, known as the requestsemaphore (section 9.5 discusses semaphores in Symbian OS). Each thread has a request semaphore associated with it that is created automatically for you by the operating system. When an asynchronous function has completed processing, it first sets the TRequestStatus variable that was passed to the function to its final state, and then signals the calling thread's request semaphore. User::WaitForRequest(status) returns when the calling thread's request semaphore is signaled, and status has a value other than KRequestPending.
User::WaitForRequest() is sometimes the most convenient way to wait for an asynchronous function to complete. In effect, it makes an asynchronous function synchronous (sometimes called 'pseudo-synchronous'). For example, you may want to call a function in a synchronous way, yet only an asynchronous version of the function exists. However, in most cases, User::WaitForRequest() should not be used since it causes your thread to stop executing until the called function is completed, and thus defeats the whole purpose of using an asynchronous function. If your code provides a user interface, it is very undesirable to block on an asynchronous function, since it isn't clear how long it will take to complete, and in the time it is blocked, your application will be unresponsive to user input.
The best way of using asynchronous functions (and what they were really designed for) is through active objects. Active objects allow you to take full advantage of asynchronous functions by allowing your application to run other code while waiting on the completion of one or more asynchronous functions.
Post a comment