Symbian3/SDK/Source/GUID-B7B7F611-BCA0-498F-BEC1-16B276F680D5.dita
changeset 7 51a74ef9ed63
parent 0 89d6a7a84779
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-B7B7F611-BCA0-498F-BEC1-16B276F680D5" xml:lang="en"><title>Calling
       
    13 Symbian Asynchronous APIs in Applications</title><shortdesc/><prolog><metadata><keywords/></metadata></prolog><conbody>
       
    14 <p>When porting an P.I.P.S.-based C or C++ application on top of Symbian C++,
       
    15 the developer may need to make use of Symbian asynchronous APIs. If asynchronous
       
    16 APIs are made use of in an P.I.P.S. application, the application needs to
       
    17 wait for the completion of the asynchronous API. This can be done in two ways:
       
    18  <ul>
       
    19 <li><p>Wait for the asynchronous request to complete. This can be achieved
       
    20 by making use of <codeph>User::WaitForRequest(iStatus)</codeph>; where <codeph>iStatus</codeph> is
       
    21 the <codeph>TRequestSemaphore</codeph> used by the asynchronous API. </p></li>
       
    22 <li><p>Call the asynchronous API in an active object, run an active scheduler,
       
    23 and let the active scheduler wait for the asynchronous operation to complete. </p></li>
       
    24 </ul></p>
       
    25 <p><b>The problems with these approaches are: </b></p>
       
    26 <p>The open source application would get blocked till the asynchronous operation
       
    27 completes in the first approach. In the second approach, the active scheduler
       
    28 would be running in a wait loop, checking for asynchronous API completion.
       
    29 Even in this case, the P.I.P.S. application would not be able to perform any
       
    30 other operations outside the active scheduler framework.</p>
       
    31 <p>The asynchronous APIs could be called in a separate process, and the P.I.P.S.
       
    32 application could communicate with this process by making use of the client/server
       
    33 framework of Symbian or by making use of other P.I.P.S. IPC mechanisms. However,
       
    34 making a different process for calling asynchronous APIs might pose a performance
       
    35 hit.</p>
       
    36 <p>One of the ways to solve these problems is to call the asynchronous APIs
       
    37 in a separate thread.</p>
       
    38 <p><b>Example:</b></p>
       
    39 <codeblock xml:space="preserve">class CActiveThread:  public CActive
       
    40 {
       
    41 public: 
       
    42 
       
    43     enum TState
       
    44     {
       
    45     EInitialized = 0x0,
       
    46     EDoFirst = 0x1,
       
    47     EDoSecond = 0x2,
       
    48     EDoThird = 0x4,
       
    49     ECompleted = 0x8
       
    50     };
       
    51  
       
    52      // thread startup routine
       
    53     static int StartMyThread(void* thisptr);
       
    54     // leaving variant of the thread startup routine
       
    55     static int StartMyThreadL(void* thisptr);
       
    56     // Helper function to start the thread
       
    57     void StartThread();    
       
    58     // Do Function
       
    59     void DoFunction(TState aState );      
       
    60               
       
    61     // CActive Functions
       
    62     void RunL();
       
    63     void DoCancel();
       
    64     		
       
    65     // Constructors and destructor      
       
    66     static CActiveThread* NewL(); 
       
    67     CActiveThread ();
       
    68     void ConstructL();
       
    69     ~ CActiveThread();      
       
    70            
       
    71 private:    
       
    72   
       
    73     // Active Scheduler
       
    74     CActiveSchedulerWait *iWait;          
       
    75     // Command/State
       
    76     TInt iState;        	    
       
    77     TRequestStatus iThreadExitWait;	    
       
    78     // my thread handle
       
    79     RThread iActiveThread;    	    
       
    80     sem_t iSem;
       
    81 };
       
    82 </codeblock>
       
    83 <p>The <codeph>StartThread</codeph> member function of <xref href="GUID-7968C6B4-3247-335A-845B-3D196E2EB14C.dita"><apiname>CActiveThread</apiname></xref> creates
       
    84 the thread which runs the active scheduler. <codeph>StartMyThread</codeph> is
       
    85 the entry point function for the new thread that starts an active scheduler
       
    86 and sets up the clean up stack. To call an asynchronous function, <codeph>DoFunction()</codeph> needs
       
    87 to be called with the corresponding state. The parent thread signals the child
       
    88 thread using the child thread’s thread request semaphore. When the thread
       
    89 request semaphore is signaled, the child thread wakes up, calls the corresponding
       
    90 asynchronous API in <codeph>RunL()</codeph> based on the <codeph>iState</codeph> and
       
    91 again goes back to the active scheduler wait loop.  </p>
       
    92 <p>To synchronize between the parent thread and the child thread, a semaphore
       
    93 can be used as shown in the following code snippet. </p>
       
    94 <codeblock xml:space="preserve">CActiveThread* CActiveThread::NewL()
       
    95 {
       
    96 CActiveThread* self = new (ELeave) CActiveThread();
       
    97 self-&gt;ConstructL();
       
    98 return self;
       
    99 }
       
   100      
       
   101 CActiveThread::CActiveThread():CActive(EPriorityStandard),iState(EInitialized)
       
   102 {       
       
   103 }
       
   104 
       
   105 void CActiveThread::ConstructL()
       
   106 {  
       
   107 // semaphore for Synching
       
   108 sem_init(&amp;iSem,0,0);  
       
   109 }
       
   110      
       
   111 void CActiveThread::StartThread()
       
   112 {       
       
   113 //Create Thread 
       
   114 TInt err = iActiveThread.Create( KThreadName(),&amp;CActiveThread::StartMyThread, KDefaultStackSize, NULL, (TAny*)this );
       
   115 iActiveThread.Logon( iThreadExitWait );
       
   116 iActiveThread.Resume();
       
   117 sem_wait(&amp;iSem );    
       
   118 }
       
   119  
       
   120 int CActiveThread::StartMyThread( void* ptr )
       
   121 {
       
   122 CActiveScheduler* scheduler = new (ELeave) CActiveScheduler();
       
   123 CActiveScheduler::Install(scheduler);     
       
   124 CTrapCleanup* pCleanup = CTrapCleanup::New();
       
   125 TRAPD(err, StartMyThreadL(ptr));        
       
   126 }
       
   127  
       
   128 int CActiveThread::StartMyThreadL( void* ptr )
       
   129 {        
       
   130 CActiveThread *thisptr = (CActiveThread*)ptr;    
       
   131 CActiveScheduler::Add(thisptr);
       
   132 thisptr-&gt;iWait = new (ELeave) CActiveSchedulerWait();	    
       
   133 thisptr-&gt;iState = EInitialized;
       
   134 thisptr-&gt;iStatus = KRequestPending;
       
   135 thisptr-&gt;SetActive();
       
   136 sem_post( &amp;(thisptr-&gt;iSem ));    
       
   137 thisptr-&gt;iWait-&gt;Start();   
       
   138 }
       
   139 
       
   140  void CActiveThread::RunL()
       
   141  {
       
   142  switch ( iState )
       
   143      {
       
   144      case  EDoFirst:
       
   145      // Call 1st asynchronous function
       
   146      break;
       
   147      
       
   148      case EDoSecond:
       
   149      // Call 2nd asynchronous function
       
   150      break;
       
   151       
       
   152      case EDoThird:
       
   153      // Call 3rd asynchronous function
       
   154      break;
       
   155      
       
   156      case ECompleted:
       
   157      iWait-&gt;AsyncStop();    
       
   158      return;			
       
   159      }
       
   160 	
       
   161 iStatus = KRequestPending;
       
   162 SetActive();
       
   163 // wake up the waiting thread
       
   164 sem_post(&amp;iSem);
       
   165 }
       
   166 
       
   167 void CActiveThread::DoCancel()
       
   168 {    
       
   169 }
       
   170 
       
   171 void CActiveThread::DoFunction(TState aState )
       
   172 {
       
   173 iState = aState;
       
   174 TRequestStatus *reqPtr = &amp;iStatus;
       
   175 iActiveThread.RequestComplete( reqPtr, KErrNone );
       
   176 sem_wait(&amp;iSem);
       
   177 }    
       
   178  
       
   179 CActiveThread::~CActiveThread()
       
   180 {  
       
   181 if ( iState != EInitialized )
       
   182     {
       
   183     iState = ECompleted;
       
   184     TRequestStatus *reqPtr = &amp;iStatus;	
       
   185     iActiveThread.RequestComplete( reqPtr, KErrNone ); 
       
   186     User::WaitForRequest( iThreadExitWait);
       
   187     }    
       
   188 sem_destroy(&amp;iSem);
       
   189 }
       
   190 </codeblock>
       
   191 <p><b>Using <xref href="GUID-7968C6B4-3247-335A-845B-3D196E2EB14C.dita"><apiname>CActiveThread</apiname></xref>:</b></p>
       
   192 <codeblock xml:space="preserve">iMyAsyncIf = CActiveThread::NewL();   
       
   193 iMyAsyncIf-&gt;StartThread();    
       
   194 iMyAsyncIf-&gt;DoFunction(EDoFirst);
       
   195 </codeblock>
       
   196 <p><b>Limitations: </b></p>
       
   197 <p>In this approach, only the parent thread communicates with the child thread.
       
   198 There is no way for the child thread to communicate with the parent thread.
       
   199  </p>
       
   200 </conbody></concept>