Symbian3/SDK/Source/GUID-B11304D7-284A-5165-9565-F9CC4405E258.dita
changeset 0 89d6a7a84779
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian3/SDK/Source/GUID-B11304D7-284A-5165-9565-F9CC4405E258.dita	Thu Jan 21 18:18:20 2010 +0000
@@ -0,0 +1,135 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
+<!-- This component and the accompanying materials are made available under the terms of the License 
+"Eclipse Public License v1.0" which accompanies this distribution, 
+and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
+<!-- Initial Contributors:
+    Nokia Corporation - initial contribution.
+Contributors: 
+-->
+<!DOCTYPE concept
+  PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
+<concept id="GUID-B11304D7-284A-5165-9565-F9CC4405E258" xml:lang="en"><title>How
+to handle multiple asynchronous requests with a wait loop</title><shortdesc>This document describes how to handle multiple asynchronous requests
+with a wait loop.</shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
+<p>A user thread which requires asynchronous services from more than one asynchronous
+service provider uses a <i>wait loop</i>.</p>
+<p>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 platform.</p>
+<p>A typical program:</p>
+<ul>
+<li id="GUID-1D4A7780-CC16-5D02-A80E-C1DB031B62A1"><p>waits for any request
+to complete by waiting on the thread’s request semaphore.</p> </li>
+<li id="GUID-E5AEA62E-4C85-55CD-96DD-02E322D8E238"><p>scans in turn through
+the asynchronous service providers for which a request is known to have been
+issued and tests the relevant <codeph>TRequestStatus</codeph> for completion;
+this is identified by a value other than <codeph>KRequestPending</codeph>.</p> </li>
+<li id="GUID-3DA7B3E5-F5CB-5853-A29F-AE78E837B9F0"><p>when the first such
+completed request has been identified, handles the completed request, possibly
+by issuing a further request to an asynchronous service provider.</p> </li>
+<li id="GUID-3A0108AF-7833-5D6C-88C0-6794EC8E0600"><p>goes back to the top
+of the wait loop and waits again.</p> </li>
+</ul>
+<p>As an example, a terminal emulator must work with multiple requests simultaneously,
+to deal with:</p>
+<ul>
+<li id="GUID-9979D5C7-72B1-53E8-BE4F-9D50ECE7AB6B"><p>key presses and user
+input in general, to control the action of the program and put characters
+on the emulated terminal screen and/or send them to the remote host</p> </li>
+<li id="GUID-A091EA85-0697-5C6D-B843-4AB3BFC7ACEC"><p>received data and to
+put characters on the emulated terminal screen or perform some control function.</p> </li>
+<li id="GUID-CF81C9D8-E73F-5474-9127-10169285B30F"><p>the completion of any
+transmit operation that was in progress; if successful, there may be more
+data to transmit; if unsuccessful, some recovery action may be necessary</p> </li>
+</ul>
+<section id="GUID-30FFEA97-13E6-4269-ABD4-F5832E6D4C09"><title>Typical wait loop protocol</title> <p>The typical protocol
+of a wait loop is:</p> <ul>
+<li id="GUID-5810F6C5-0E37-53B0-AE99-5C9FF0295709"><p>The initialization phase
+which issues the first asynchronous requests.</p> </li>
+<li id="GUID-A4C2AAD7-EDDE-50B3-9B60-1DC0D7AD84A0"><p>Entry into the main
+loop which waits for <i>any</i> of these requests to complete and then handles
+the completion of one of them.</p> </li>
+<li id="GUID-3119355F-B74D-5AB3-AC77-FD0206411F8F"><p>Detection of conditions
+which imply termination of the program. Typically, one of the request completion
+handlers sets appropriate flags and the wait loop terminates.</p> </li>
+<li id="GUID-F4323300-37BB-5BCD-926C-E3EAB1F8018E"><p>Cleanup and final termination.</p> </li>
+</ul> <codeblock id="GUID-D788337C-777D-533A-8832-8B4F669B005E" xml:space="preserve">initialize;
+while (!finished())
+    {
+    wait for one or more requests to complete
+    decide which request completed, and handle it
+    }
+terminate;</codeblock> <p>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.</p> </section>
+<section id="GUID-1487241F-94B2-46BC-BEDD-7079E2ED968D"><title>Multiple outstanding requests</title> <p>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.</p> <p>In the following example:</p> <ul>
+<li id="GUID-E29D808F-332E-5859-8693-A94C76597BDC"><p>Call <codeph>Initialize()</codeph> to
+initialize the emulator.</p> </li>
+<li id="GUID-0DAA2678-04D4-584A-80C2-814457662D7B"><p>Implement <codeph>while()</codeph> to
+handle events.</p> </li>
+<li id="GUID-012E4941-8119-5047-A07B-FC3CB9A1A916"><p>Call the function <codeph>User::WaitForAnyRequest()</codeph> to
+wait for any request to complete instead of waiting for a specific request
+to complete.</p> </li>
+<li id="GUID-412709CA-945B-547F-8D73-7E282BF02223"><p>Identify the particular
+request that completed by checking the request status objects for a value
+not equal to <codeph>KRequestPending</codeph>.</p> </li>
+</ul> <codeblock id="GUID-99FCFA14-81E8-5594-A716-BDE02B237F44" xml:space="preserve">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
+    ...
+    };</codeblock> <codeblock id="GUID-1F3EBBF4-4141-5B4F-9B75-EFD3D820441B" xml:space="preserve">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 weren’t expecting
+                    // panic !
+                    }
+        }
+    }</codeblock> <p><b>Note</b> </p> <ul>
+<li id="GUID-12F90A7C-738C-5A3D-B4BB-1604B9FA0534"><p>The request status is
+set by the service provider to <codeph>KRequestPending</codeph> when a request
+is issued. When the request is complete, the service provider uses an operating
+system call to set the request status value to some other value — usually
+a standard error code — and then to wake up the thread that requested
+the service, causing its <codeph>WaitForAnyRequest()</codeph> to complete.</p> </li>
+</ul> </section>
+</conbody></concept>
\ No newline at end of file