examples/Base/IPC/Async/Fibonacci2/Fibonacci2.cpp

00001 // Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
00002 // All rights reserved.
00003 // This component and the accompanying materials are made available
00004 // under the terms of "Eclipse Public License v1.0"
00005 // which accompanies this distribution, and is available
00006 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
00007 //
00008 // Initial Contributors:
00009 // Nokia Corporation - initial contribution.
00010 //
00011 // Contributors:
00012 //
00013 // Description:
00014 // Example wraps a console in an active object and performs the 
00015 // Fibonacci calculation in a separate thread.
00016 // This is NOT the recommended way and serves only to compare with the 
00017 // Fibonacci3 example which performs the calculation as
00018 // a background active object.
00019 //
00020 
00021 
00022 #include <e32std.h>
00023 #include <e32cons.h>
00024 #include <e32base.h>
00025 
00026 //
00027 // Common literals
00028 //
00029 _LIT(KTxtFibThread,"FibThread");
00030 
00031 
00032 LOCAL_D CConsoleBase* console;
00033 
00034 _LIT(KTxtMainInstructions,"\n\nPress 'F' to start\n      'ESC' to exit\n      'C' to cancel, anytime\n");
00035 
00037 //
00038 // -----> CActiveConsole (definition)
00039 //
00040 // An abstract class which provides the facility to issue key requests. 
00041 //
00043 class CActiveConsole : public CActive
00044         {
00045 public:
00046           // Construction
00047         CActiveConsole(CConsoleBase* aConsole);
00048         void ConstructL();
00049 
00050           // Destruction
00051         ~CActiveConsole();
00052 
00053           // Issue request
00054         void RequestCharacter();
00055         
00056           // Cancel request.
00057           // Defined as pure virtual by CActive;
00058           // implementation provided by this class.
00059         void DoCancel();
00060 
00061           // Service completed request.
00062           // Defined as pure virtual by CActive;
00063           // implementation provided by this class,
00064         void RunL();
00065 
00066           // Called from RunL() - an implementation must be provided
00067           // by derived classes to handle the completed request
00068         virtual void ProcessKeyPress(TChar aChar) = 0; 
00069           
00070 protected:
00071           // Data members defined by this class
00072         CConsoleBase* iConsole; // A console for reading from
00073         };
00074 
00075 
00077 //
00078 // -----> CExampleScheduler (definition)
00079 //
00081 
00082 class CExampleScheduler : public CActiveScheduler
00083         {
00084 public:
00085         void Error (TInt aError) const;
00086         void WaitForAnyRequest();
00087         void SetActiveObject(CActiveConsole* aActiveConsole);
00088 private:
00089           // data members defined for this class
00090         CActiveConsole* iActiveConsole;
00091         };
00092 
00093 
00095 //
00096 // -----> CFibonacciEngine (definition)
00097 //
00098 // This class provides the fibonacci calculation engine
00099 //
00101 
00102 class CFibonacciEngine : public CBase
00103         {
00104 public:
00105         void Calculate (TInt aTerms) ;
00106 
00107         TUint iResult ;
00108         } ;
00109 
00110 
00112 //
00113 // -----> TFibonacciParameters (definition)
00114 //
00115 // This class provides for passing parameters to the thread 
00116 //
00118 
00119 class TFibonacciParameters
00120         {
00121 public:
00122         TInt iVar1 ;
00123         TAny* iVar2 ;
00124         TUint iResult ;
00125         } ;
00126 
00127 
00129 //
00130 // -----> CFibonacciThreadHandler (definition)
00131 //
00132 // This class encapsulates the fibonacci thread that runs the fibonacci engine
00133 //
00135 
00136 class CFibonacciThreadHandler : public CActive
00137         {
00138 public:
00139         CFibonacciThreadHandler(CConsoleBase* aConsole, CFibonacciEngine* aFibonacciEngine) ;
00140         ~CFibonacciThreadHandler() ;
00141 
00142         void CalculateFibonacciL(TInt aIterations) ;
00143 
00144 private:
00145         void DoCancel() ;
00146         void RunL() ;
00147         static TInt FibonacciThread(TAny* aParameters) ;
00148 
00149 private:
00150         CConsoleBase* iConsole ;
00151         TFibonacciParameters iFibonacciParameters ;
00152         CFibonacciEngine* iFibonacciEngine ;
00153         };
00154 
00155 
00157 //
00158 // -----> CFibonacciKeyHandler (definition)
00159 //
00160 // This class encapsulates the fibonacci keyboard handler
00161 //
00163 
00164 class CFibonacciKeyHandler : public CActiveConsole
00165         {
00166 public:
00167         CFibonacciKeyHandler(   CConsoleBase* aConsole, 
00168                                                         CFibonacciThreadHandler* iThreadHandler) ;
00169         void ConstructL();
00170 
00171           // Static construction
00172         static CFibonacciKeyHandler* NewLC(CConsoleBase* aConsole, CFibonacciThreadHandler* aHandler) ;
00173 
00174           // service request
00175         void ProcessKeyPress(TChar aChar) ;
00176 
00177 private:
00178         CConsoleBase* iConsole ;
00179         CFibonacciThreadHandler* iThreadHandler ;
00180         };
00181 
00182 
00183 
00184 
00186 //
00187 // -----> CActiveConsole (implementation)
00188 //
00190 CActiveConsole::CActiveConsole( CConsoleBase* aConsole) 
00191         : CActive(CActive::EPriorityUserInput)
00192           // Construct high-priority active object
00193         {
00194         iConsole = aConsole;
00195         }
00196 
00197 void CActiveConsole::ConstructL()
00198         {
00199           // Add to active scheduler
00200         CActiveScheduler::Add(this);
00201         }
00202 
00203 CActiveConsole::~CActiveConsole()
00204         {
00205         // Make sure we're cancelled
00206         Cancel();
00207         }
00208 
00209 void  CActiveConsole::DoCancel()
00210         {
00211         iConsole->ReadCancel();
00212         }
00213 
00214 void  CActiveConsole::RunL()
00215         {
00216           // Handle completed request
00217         ProcessKeyPress(TChar(iConsole->KeyCode()));
00218         }
00219 
00220 void CActiveConsole::RequestCharacter()
00221         {
00222           // A request is issued to the CConsoleBase to accept a
00223           // character from the keyboard.
00224         iConsole->Read(iStatus); 
00225         SetActive();
00226         }
00227 
00228 
00230 //
00231 // -----> CExampleScheduler (implementation)
00232 //
00234 void CExampleScheduler::Error(TInt aError) const
00235         {
00236         _LIT(KTxtSchedulerError,"CExampleScheduler - error");
00237         User::Panic(KTxtSchedulerError,aError);
00238         }
00239 
00240 
00241 void CExampleScheduler::WaitForAnyRequest()
00242         {
00243         if (!(iActiveConsole->IsActive()))
00244                 iActiveConsole->RequestCharacter();     
00245         CActiveScheduler::WaitForAnyRequest();
00246         }
00247 
00248 void CExampleScheduler::SetActiveObject(CActiveConsole* aActiveConsole)
00249         {
00250         iActiveConsole = aActiveConsole;
00251         }
00252 
00253 
00254 
00255 
00256 
00258 // CFibonacciKeyHandler support routine
00259 //   uses up arrow & down arrow to change number, Enter to select
00261 
00262 TInt GetValueFromKeyboard (TInt aInitial, TInt aStep, TInt lowerLimit, TInt upperLimit, const TDesC& aPrompt, CConsoleBase* aConsole)
00263         {
00264         TChar input ;
00265         TInt value = aInitial ;
00266 
00267         aConsole->Printf(aPrompt) ;
00268         do
00269                 {
00270                 aConsole->SetPos(0);
00271                 _LIT(KFormat1,"%d  ");
00272                 aConsole->Printf(KFormat1, value);
00273                 input = aConsole->Getch() ;
00274                 if (input == EKeyUpArrow && value < upperLimit) value = value + aStep ;
00275                 if (input == EKeyDownArrow && value > lowerLimit) value = value - aStep ;
00276                 }
00277         while (input != EKeyEnter) ;
00278 
00279         return value ;
00280         }
00281 
00282 
00284 //
00285 // -----> CFibonacciKeyHandler (implementation)
00286 //
00288 
00289 
00290 CFibonacciKeyHandler::CFibonacciKeyHandler(CConsoleBase* aConsole, CFibonacciThreadHandler* aThreadHandler )
00291         : CActiveConsole(aConsole)
00292           // construct zero-priority active object
00293         {
00294         iConsole = aConsole ;
00295         iThreadHandler = aThreadHandler ;
00296           // Add to active scheduler
00297         CActiveScheduler::Add(this);
00298           // Make this the active object
00299         ((CExampleScheduler*)(CActiveScheduler::Current()))->SetActiveObject(this);
00300         } 
00301 
00302 
00303 void CFibonacciKeyHandler::ProcessKeyPress(TChar aChar)
00304         {
00305           // if key is ESC 
00306           //   cancel any outstanding request
00307           //   stop the scheduler
00308         if (aChar == EKeyEscape)
00309                 {
00310                 CActiveScheduler::Stop();
00311                 return;
00312                 }
00313 
00314           // If key is "f" or "F"
00315           //   cancel any outstanding request
00316           //   issue a fibonacci request.
00317         if (aChar == 'f' || aChar == 'F') 
00318                 {
00319                 _LIT(KTxtStartingFibonacci,"\nStarting Fibonacci....  \n");
00320                 iConsole->Printf(KTxtStartingFibonacci);
00321                 _LIT(KTxtReturnTermNumber,"\nENTER selects num\nUP    arrow increases num\nDOWN  arrow decreases num\n\n");
00322                 TInt iterations = GetValueFromKeyboard(5,1,2,46, KTxtReturnTermNumber, iConsole) ;
00323                 TRAPD(err,iThreadHandler->CalculateFibonacciL(iterations));
00324                 if(err)
00325                         {
00326                                 _LIT(KFormat4,"CalculateFibonacciL failed: leave code=%d");
00327                                 console->Printf(KFormat4, err); 
00328                         }
00329                 return;
00330                 }
00331 
00332       // If key is "c" or "C" 
00333           //    cancel any outstanding request  
00334         if (aChar == 'c' || aChar == 'C')
00335                 {
00336                 _LIT(KTxtCancelFibonacci,"\nCancelling Fibonacci....  \n");
00337                 iConsole->Printf(KTxtCancelFibonacci);
00338                 iThreadHandler->Cancel();
00339                 iConsole->Printf(KTxtMainInstructions);
00340                 return;
00341                 }
00342 
00343         _LIT(KTxtNotRecognised,"\nUnwanted key pressed");
00344         iConsole->Printf(KTxtNotRecognised);
00345         iConsole->Printf(KTxtMainInstructions);
00346         }
00347 
00348 
00350 //
00351 // -----> CFibonacciThreadHandler (implementation)
00352 //
00354 
00355 CFibonacciThreadHandler::CFibonacciThreadHandler(CConsoleBase* aConsole, CFibonacciEngine* aFibonacciEngine)
00356 //
00357 // Constructor
00358 //
00359         : CActive(EPriorityStandard)
00360         {
00361         iConsole = aConsole ;
00362         iFibonacciEngine = aFibonacciEngine ;
00363         CActiveScheduler::Add(this);
00364         };
00365 
00366 
00367 // destructor
00368 CFibonacciThreadHandler::~CFibonacciThreadHandler() 
00369         {
00370         // cancel any requests and tell server 
00371         Cancel() ;
00372         }
00373 
00374 
00375 void CFibonacciThreadHandler::DoCancel() 
00376         {
00377         // cancel the active object request 
00378         RThread thread ;
00379         thread.Open(KTxtFibThread) ;
00380         thread.Close() ;
00381         }
00382 
00383 
00384 void CFibonacciThreadHandler::RunL() 
00385         {
00386         // handle requests - print out result and flag as handled (ie not cancelled)
00387         _LIT(KFormat2,"    Result : %u \n");  //not used
00388         iConsole->Printf(KFormat2, iFibonacciParameters.iResult) ;
00389         iConsole->Printf(KTxtMainInstructions);
00390         }
00391 
00392 
00393 // initiate a request
00394 void CFibonacciThreadHandler::CalculateFibonacciL(TInt aIterations)
00395         {
00396         const TInt KHeapSize = 0x800 ;
00397         
00398         _LIT(KTxtFibRequested,"\nFibonacci requested ...  ");
00399         iConsole->Printf(KTxtFibRequested);
00400 
00401 
00402         RThread thread ;
00403 
00404         // set up parameters to thread
00405 
00406         iFibonacciParameters.iVar1 = aIterations ;
00407         iFibonacciParameters.iVar2 = iFibonacciEngine ;
00408 
00409         // generate thread, leave if fails
00410         
00411         TInt result = thread.Create(KTxtFibThread,(TThreadFunction)FibonacciThread, KDefaultStackSize,
00412                                                                 KMinHeapSize, KHeapSize, &iFibonacciParameters, EOwnerThread) ;
00413         User::LeaveIfError(result) ;
00414 
00415         // log on to thread -   sets iStatus to KRequestPending 
00416         //                                              requests notification of thread completion
00417         thread.Logon(iStatus) ;
00418 
00419         // give thread low priority 
00420         thread.SetPriority(EPriorityMuchLess) ;
00421 
00422         // resume thread (wake it up sometime after this function returns)
00423         thread.Resume() ;
00424 
00425         thread.Close() ;
00426 
00427         // ensure scheduler checks status 
00428         SetActive() ;
00429         
00430         _LIT(KTxtOK,"OK  \n");
00431         iConsole->Printf(KTxtOK);
00432         }
00433 
00434 
00436 //  Thread routine that sorts out parameters & calls engine
00438 
00439 TInt CFibonacciThreadHandler::FibonacciThread(TAny* aParameters)
00440         {
00441         // cast the parameters pointer
00442         TFibonacciParameters* parameters = (TFibonacciParameters*) aParameters ;
00443 
00444         // get variables from parameters class
00445         TInt iterations = parameters->iVar1 ;
00446         CFibonacciEngine* fibonacciEngine = (CFibonacciEngine*)parameters->iVar2 ;
00447 
00448         // call the engine
00449         fibonacciEngine->Calculate(iterations) ;
00450 
00451         // store result
00452         parameters->iResult = fibonacciEngine->iResult ;
00453 
00454         return KErrNone ;
00455 }
00456 
00457 
00459 //
00460 // -----> CFibonacciEngine (implementation)
00461 //
00463 
00464 void CFibonacciEngine::Calculate (TInt aTerms) 
00465         {
00466         TInt iterations = aTerms ;
00467 
00468         TInt currentTotal = 1 ;
00469         TInt previousTotal = 0 ;
00470         _LIT(KTxtTooManyIterations,"Too many iterations");
00471         __ASSERT_ALWAYS(iterations<47,User::Panic(KTxtTooManyIterations,iterations));
00472 
00473 
00474         // if limit not yet reached
00475         while (iterations-- > 0)        
00476                 {
00477                 // calculate next number in series
00478                 TInt newTotal = currentTotal + previousTotal ;
00479 
00480                 // update variables
00481                 previousTotal = currentTotal ;
00482                 currentTotal = newTotal ;
00483 
00484                 // introduce a delay
00485                 User::After(1000000) ;
00486                 }  
00487 
00488         iResult = currentTotal ;
00489 
00490 //UserHal::ModifyLedMask(1,2);
00491         } 
00492 
00493 
00495 // This section deals with initialisation and ensuring we have a console active
00497 
00498 void doExampleL () ;
00499 
00500 void SetupConsoleL();
00501 
00502 GLDEF_C TInt E32Main()                          // main function called by E32
00503     {
00504         CTrapCleanup* cleanup=CTrapCleanup::New();              // get clean-up stack
00505         TRAPD(error,SetupConsoleL());                                   // more initialization, then do example
00506         _LIT(KTxtFibonacciExampleError,"Fibonacci example error");
00507         __ASSERT_ALWAYS(!error,User::Panic(KTxtFibonacciExampleError,error));
00508         delete cleanup;                                                                 // destroy clean-up stack
00509         return 0;                                                                               // and return
00510     }
00511 
00512 void SetupConsoleL()                             // initialize and call example code under cleanup stack
00513     {
00514         _LIT(KTxtFibActObjInThread,"Active Object and thread");
00515         console=Console::NewL(KTxtFibActObjInThread,TSize(KConsFullScreen,KConsFullScreen));
00516         CleanupStack::PushL(console);
00517         console->Printf(KTxtMainInstructions) ;
00518         TRAPD(error, doExampleL());                                                     // perform example function
00519         if (error)
00520                 {
00521                 _LIT(KFormat3,"failed: leave code=%d");
00522                 console->Printf(KFormat3, error);
00523                 }
00524         _LIT(KTxtPressAnyKey,"[Press any key to exit]");
00525         console->Printf(KTxtPressAnyKey);
00526         console->Getch();                                                               // get and ignore character
00527         CleanupStack::PopAndDestroy(console);                                   // close console
00528     }
00529 
00530 
00532 //
00533 // Do the example
00534 //
00536 void doExampleL()
00537     {
00538           // Construct and install the active scheduler; push onto cleanup stack.
00539         CExampleScheduler*  exampleScheduler = new (ELeave) CExampleScheduler;
00540         CleanupStack::PushL(exampleScheduler);
00541          
00542           // Install as the active scheduler
00543         CActiveScheduler::Install(exampleScheduler);
00544 
00545         // Create CFibonacciEngine active object; push onto cleanup stack.
00546         CFibonacciEngine* fibEngine = new (ELeave) CFibonacciEngine ;
00547     CleanupStack::PushL(fibEngine);
00548 
00549           // Create CFibonacciThreadHandler active object; push onto cleanup stack.
00550         CFibonacciThreadHandler* fibThreadHandler = new (ELeave) CFibonacciThreadHandler(console, fibEngine);
00551     CleanupStack::PushL(fibThreadHandler);
00552         
00553           // Create CFibonacciKeyHandler active object; push onto cleanup stack.
00554         CFibonacciKeyHandler* fibKeyHandler = new (ELeave) CFibonacciKeyHandler(console, fibThreadHandler);
00555     CleanupStack::PushL(fibKeyHandler); 
00556 
00557           // issue initial request; push onto cleanup stack
00558         fibKeyHandler->RequestCharacter() ;
00559                         
00560         // Main part of the program:
00561         //    wait loop that cycles until ActiveScheduler::Stop called
00562         CActiveScheduler::Start();
00563 
00564         // Remove from the cleanup stack and destroy:
00565         CleanupStack::PopAndDestroy(4); 
00566         }
00567 
00568 
00569 
00570 

Generated by  doxygen 1.6.2