--- /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