Symbian3/SDK/Source/GUID-2161BD64-889B-5EAB-B023-1162FE9619DB.dita
changeset 7 51a74ef9ed63
child 8 ae94777fff8f
equal deleted inserted replaced
6:43e37759235e 7:51a74ef9ed63
       
     1 <?xml version="1.0" encoding="utf-8"?>
       
     2 <!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
       
     3 <!-- This component and the accompanying materials are made available under the terms of the License 
       
     4 "Eclipse Public License v1.0" which accompanies this distribution, 
       
     5 and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
       
     6 <!-- Initial Contributors:
       
     7     Nokia Corporation - initial contribution.
       
     8 Contributors: 
       
     9 -->
       
    10 <!DOCTYPE concept
       
    11   PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
       
    12 <concept id="GUID-2161BD64-889B-5EAB-B023-1162FE9619DB" xml:lang="en"><title>How
       
    13 to use multiple active objects</title><shortdesc>This document illustrates how to use one active object to control
       
    14 another.</shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
       
    15 <p>The following example code fragments show how to construct a program with
       
    16 two active objects, where one controls the initiation and cancellation of
       
    17 the other.</p>
       
    18 <p>In these examples:</p>
       
    19 <p><codeph>CActiveConsole</codeph> is an active object and contains a pointer
       
    20 to a <codeph>CConsoleBase</codeph> object which is a service provider. Through
       
    21 this service provider, the active object provides the facility to request
       
    22 a character from the keyboard.</p>
       
    23 <p><codeph>RunL()</codeph> delegates the handling of completed requests to
       
    24 the pure virtual function <codeph>ProcessKeyPress()</codeph>, which must be
       
    25 provided by a derived class.</p>
       
    26 <p><codeph>CMessageKeyProcessor</codeph> is further derived from <codeph>CActiveConsole</codeph> and
       
    27 contains a pointer to another active object <codeph>CExampleActiveObject</codeph>,
       
    28 which requires input from the keyboard.</p>
       
    29 <p>Depending on the input character, the <codeph>CMessageKeyProcessor</codeph> active
       
    30 object does one of the following:</p>
       
    31 <ul>
       
    32 <li id="GUID-9151F698-3D4F-5C3D-A758-194018FC053C"><p>issues a request to
       
    33 the <codeph>CExampleActiveObject</codeph> active object</p> </li>
       
    34 <li id="GUID-FBF8743F-0147-502B-BBE8-824DB727F791"><p>cancels any outstanding
       
    35 request to the <codeph>CExampleActiveObject</codeph> active object</p> </li>
       
    36 <li id="GUID-2E714DE6-AAE1-5926-8026-9B6E1C09C5C7"><p>does nothing</p> </li>
       
    37 </ul>
       
    38 <p>The implementation of the <codeph>CExampleActiveObject</codeph> active
       
    39 object is not relevant to the example and is not shown.</p>
       
    40 <p>The following diagram shows the relationship between the classes.</p>
       
    41 <fig id="GUID-AF998428-D142-56F8-8967-AF66AF9119F8">
       
    42 <image href="GUID-BEDF6765-4BF4-532F-A2C7-F052FE8A9CA2_d0e236747_href.png" placement="inline"/>
       
    43 </fig>
       
    44 <section id="GUID-5E2A6378-546D-46C5-8081-6425A96FAAFF"><title>Encapsulating the service provider</title> <p>The class <codeph>CActiveConsole</codeph> encapsulates
       
    45 the provision of basic keyboard services. Its <codeph>iConsole</codeph> data
       
    46 member is a pointer to the service provider, the <codeph>CConsoleBase</codeph> object.</p> <p>The
       
    47 active object class is defined as:</p> <codeblock id="GUID-DC98E432-1927-55F5-94A3-68D2493B75E8" xml:space="preserve">class CActiveConsole : public CActive
       
    48     {
       
    49 public:
       
    50     CActiveConsole(CConsoleBase* aConsole);
       
    51     void ConstructL();
       
    52     ~CActiveConsole();
       
    53     void RequestCharacter();
       
    54     void RunL();
       
    55     void DoCancel();
       
    56     virtual void ProcessKeyPress(TChar aChar)=0;
       
    57 protected:
       
    58     CConsoleBase* iConsole; 
       
    59     };</codeblock> <p>The class constructor takes a pointer to a <codeph>CConsoleBase</codeph> object
       
    60 as its single argument and initializes its <codeph>iConsole</codeph> data
       
    61 member to this value:</p> <codeblock id="GUID-2C5C49DB-AE88-5F84-82D7-BA5680A286C8" xml:space="preserve">CActiveConsole::CActiveConsole(CConsoleBase* aConsole)
       
    62     : iConsole(aConsole)
       
    63     {}</codeblock> <p>The <codeph>ConstructL()</codeph> function adds the
       
    64 active object to the active scheduler:</p> <codeblock id="GUID-CE947B19-9664-5774-ABFB-17E79A112131" xml:space="preserve">void CActiveConsole::ConstructL()
       
    65     {
       
    66     CActiveScheduler::Add(this);
       
    67     }</codeblock> <p>The destructor cancels any outstanding request before
       
    68 destroying the active object:</p> <codeblock id="GUID-0120EE92-2BD8-5B2E-841A-DC366B3BED12" xml:space="preserve">CActiveConsole::~CActiveConsole()
       
    69     {
       
    70     Cancel();
       
    71     }</codeblock> <p><codeph>DoCancel()</codeph> is implemented to cancel
       
    72 the request to <codeph>iConsole</codeph>.</p> <p>The <codeph>RequestCharacter()</codeph> function
       
    73 makes a request for a key press to the service provider by calling <codeph>iConsole-&gt;Read(iStatus)</codeph> and
       
    74 setting the active request flag:</p> <codeblock id="GUID-EF731B8D-7001-503F-8167-7A10697D5202" xml:space="preserve">void CActiveConsole::RequestCharacter()
       
    75     {
       
    76     iConsole-&gt;Read(iStatus);
       
    77     SetActive();
       
    78     }</codeblock> <p>The <codeph>RunL()</codeph> function makes a call to
       
    79 the <codeph>ProcessKeyPress()</codeph> function. This is a pure virtual function
       
    80 that derived classes must implement to handle the key press and to reissue
       
    81 the request:</p> <codeblock id="GUID-DF9F07BB-2099-5310-8921-3A290580B4AF" xml:space="preserve">void CActiveConsole::RunL()
       
    82     {
       
    83     ProcessKeyPress(TChar(iConsole-&gt;KeyCode()));
       
    84     }</codeblock> </section>
       
    85 <section id="GUID-FFD3321F-3A46-4C40-A779-39C142DC79C3"><title>Further deriving from the active object</title> <p>The class <codeph>CMessageKeyProcessor</codeph> is
       
    86 a concrete class, derived from <codeph>CActiveConsole</codeph>. It provides
       
    87 an implementation for the<codeph>ProcessKeyPress()</codeph> function and can
       
    88 issue or cancel requests to a<codeph>CExampleActiveObject</codeph> active
       
    89 object.</p> <p>This active object class is defined as:</p> <codeblock id="GUID-C5F51E0D-517C-523D-BADA-4B3CDCA53073" xml:space="preserve">class CMessageKeyProcessor : public CActiveConsole
       
    90     {
       
    91 public:
       
    92     ...
       
    93     CMessageKeyProcessor(CConsoleBase* aConsole, CExampleActiveObject* iExampleObject);
       
    94     void ProcessKeyPress(TChar aChar);
       
    95 private:
       
    96     CExampleActiveObject* iExampleObject;
       
    97     };</codeblock> <p><b>Notes</b> </p> <ul>
       
    98 <li id="GUID-2341BA65-3806-5354-9F9D-EB1A8FD3FD61"><p>The first constructor
       
    99 parameter specifies a <codeph>CConsoleBase</codeph> which will be used to
       
   100 provide asynchronous keyboard input.</p> </li>
       
   101 <li id="GUID-E9CAAF35-C404-5418-9720-F560C4CED53D"><p>the second constructor
       
   102 parameter specifies a <codeph>CExampleActiveObject</codeph> which will be
       
   103 controlled by this <codeph>CMessageKeyProcessor</codeph>.</p> </li>
       
   104 </ul> <p>The behaviour of the <codeph>ProcessKeyPress()</codeph> function
       
   105 depends on the key code value:</p> <codeblock id="GUID-8081A453-4D44-5F2B-BAF3-7A43A1417BEF" xml:space="preserve">void CMessageKeyProcessor::ProcessKeyPress(TChar aChar)
       
   106     {
       
   107     if (aChar == 'm' || aChar == 'M')
       
   108         {
       
   109         iExampleObject-&gt;Cancel();
       
   110         iExampleObject-&gt;IssueRequest();
       
   111         }
       
   112     if (aChar == 'c' || aChar == 'C')
       
   113         {
       
   114         iExampleObject-&gt;Cancel();
       
   115         }
       
   116     if (aChar != EKeyEscape)
       
   117         {
       
   118         RequestCharacter();
       
   119         }
       
   120     else
       
   121         {
       
   122         iExampleObject-&gt;Cancel();
       
   123         CActiveScheduler::Stop();
       
   124         }
       
   125     }</codeblock> </section>
       
   126 <section id="GUID-91B9EF85-A595-479D-8D57-40CC427C19E7"><title>Enhanced framework</title> <p>In the code fragment below,
       
   127 an active scheduler is created to which both a <codeph>CMessageKeyProcessor</codeph> active
       
   128 object and a<codeph>CExampleActiveObject</codeph> active object are added:</p> <codeblock id="GUID-830AA24C-7781-505A-9DD1-4A042040688D" xml:space="preserve">LOCAL_C void doExampleL()
       
   129     {
       
   130     CActiveScheduler* exampleScheduler=new (ELeave) CActiveScheduler;
       
   131     CleanupStack::PushL(exampleScheduler);
       
   132     CActiveScheduler::Install(exampleScheduler);
       
   133 
       
   134     CExampleActiveObject* iExampleObject =
       
   135             CExampleActiveObject::NewLC();
       
   136     CMessageKeyProcessor* keyProcessor=
       
   137              CMessageKeyProcessor::NewLC(console, iExampleObject);
       
   138 
       
   139     keyProcessor-&gt;RequestCharacter();
       
   140     CActiveScheduler::Start();
       
   141     CleanupStack::PopAndDestroy(3);
       
   142     }</codeblock> <p><b>Notes</b> </p> <ul>
       
   143 <li id="GUID-1FB2DB58-C282-5B21-A070-DEC020E98059"><p>An instance of the active
       
   144 scheduler, <codeph>exampleScheduler</codeph> is pushed onto the cleanup stack
       
   145 and installed as the current active scheduler.</p> </li>
       
   146 <li id="GUID-3404475D-4044-5DB4-BEDF-5A308B2521CA"><p>An instance of the <codeph>CExampleActiveObject</codeph> active
       
   147 object is created.</p> </li>
       
   148 <li id="GUID-F7C3C84D-66E5-5F8D-8213-8DC3864D659D"><p>An instance of the <codeph>CMessageKeyProcessor</codeph> active
       
   149 object is created and this is in control.</p> </li>
       
   150 <li id="GUID-DA61DFD2-B057-50C9-8FD1-C53E884A4A0E"><p><codeph>keyProcessor-&gt;RequestCharacter()</codeph> issues
       
   151 a request for keyboard input.</p> </li>
       
   152 <li id="GUID-5BFAEEED-051C-5741-BAA0-96AFC3EA5A02"><p><codeph>CActiveScheduler::Start()</codeph> starts
       
   153 the active scheduler. At least one outstanding request is necessary before
       
   154 the wait loop is started, otherwise the thread hangs. All further request
       
   155 issuing and servicing occurs within this function. The wait loop continues
       
   156 until one of the active objects’ <codeph>RunL()</codeph> calls<codeph>CActiveScheduler::Stop()</codeph>.</p> </li>
       
   157 <li id="GUID-E3FB7738-DC6C-5472-8CBF-FAAD47C440D5"><p>The active objects and
       
   158 the active scheduler are popped from the cleanup stack and destroyed.</p> </li>
       
   159 </ul> </section>
       
   160 </conbody></concept>