examples/Base/IPC/Async/Fibonacci1/Fibonacci1.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.
00015 // Calculates Fibonacci number as chosen by the user. Note that, in this
00016 // example, the calculation is done as part of the console active object's 
00017 // RunL() and can take a long time to complete. It also means that nothing
00018 // else can happen (including responding to keyboard events) until the 
00019 // calculation is complete. 
00020 //
00021 
00022 
00023 
00024 #include <e32base.h>
00025 #include <e32cons.h>
00026 #include <e32std.h>
00027 
00028 
00029 LOCAL_D CConsoleBase* console;
00030 
00031 _LIT(KTxtMainInstructions,"\n\nPress 'F' to start\n      'ESC' to exit.\n");
00032 
00034 //
00035 // -----> CActiveConsole (definition)
00036 //
00037 // An abstract class which provides the facility to issue key requests. 
00038 //
00040 
00041 class CActiveConsole : public CActive
00042         {
00043 public:
00044           // Construction
00045         CActiveConsole(CConsoleBase* aConsole);
00046         void ConstructL();
00047 
00048           // Destruction
00049         ~CActiveConsole();
00050 
00051           // Issue request
00052         void RequestCharacter();
00053         
00054           // Cancel request.
00055           // Defined as pure virtual by CActive;
00056           // implementation provided by this class.
00057         void DoCancel();
00058 
00059           // Service completed request.
00060           // Defined as pure virtual by CActive;
00061           // implementation provided by this class,
00062         void RunL();
00063 
00064           // Called from RunL() - an implementation must be provided
00065           // by derived classes to handle the completed request
00066         virtual void ProcessKeyPress(TChar aChar) = 0; 
00067           
00068 protected:
00069           // Data members defined by this class
00070         CConsoleBase* iConsole; // A console for reading from
00071         };
00072 
00073 
00075 //
00076 // -----> CExampleScheduler (definition)
00077 //
00079 
00080 class CExampleScheduler : public CActiveScheduler
00081         {
00082 public:
00083         void Error (TInt aError) const;
00084         void WaitForAnyRequest();
00085         void SetActiveObject(CActiveConsole* aActiveConsole);
00086 private:
00087           // data members defined for this class
00088         CActiveConsole* iActiveConsole;
00089         };
00090 
00091 
00093 //
00094 // -----> TFibonacciEngine (definition)
00095 //
00096 // This class provides the fibonacci calculation engine
00097 //
00099 
00100 class TFibonacciEngine
00101         {
00102 public:
00103         void Calculate (TInt aTerms) ;
00104 
00105         TInt iResult ;
00106         } ;
00107 
00108 
00110 //
00111 // -----> CFibonacciApplication (definition)
00112 //
00113 // This class encapsulates the fibonacci calculation engine
00114 //
00116 
00117 class CFibonacciApplication : public CActiveConsole
00118         {
00119 public:
00120         CFibonacciApplication(CConsoleBase* aConsole) ;
00121         void ConstructL();
00122 
00123           // Static construction
00124         static CFibonacciApplication* NewLC(CConsoleBase* aConsole) ;
00125 
00126           // service request
00127         void ProcessKeyPress(TChar aChar) ;
00128 
00129 private:
00130         CConsoleBase* iConsole ;
00131         TFibonacciEngine iFibonacciEngine ;
00132         };
00133 
00134 
00136 //
00137 // -----> CActiveConsole (implementation)
00138 //
00140 
00141 CActiveConsole::CActiveConsole( CConsoleBase* aConsole) 
00142         : CActive(CActive::EPriorityUserInput)
00143           // Construct high-priority active object
00144         {
00145         iConsole = aConsole;
00146         __DECLARE_NAME(_S("CActiveConsole"));
00147 
00148         }
00149 
00150 void CActiveConsole::ConstructL()
00151         {
00152           // Add to active scheduler
00153         CActiveScheduler::Add(this);
00154         }
00155 
00156 CActiveConsole::~CActiveConsole()
00157         {
00158         // Make sure we're cancelled
00159         Cancel();
00160         }
00161 
00162 void  CActiveConsole::DoCancel()
00163         {
00164         iConsole->ReadCancel();
00165         }
00166 
00167 void  CActiveConsole::RunL()
00168         {
00169           // Handle completed request
00170         ProcessKeyPress(TChar(iConsole->KeyCode()));
00171         }
00172 
00173 void CActiveConsole::RequestCharacter()
00174         {
00175           // A request is issued to the CConsoleBase to accept a
00176           // character from the keyboard.
00177         iConsole->Read(iStatus); 
00178         SetActive();
00179         }
00180 
00181 
00183 //
00184 // -----> CExampleScheduler (implementation)
00185 //
00187 
00188 void CExampleScheduler::Error(TInt aError) const
00189         {
00190         _LIT(KTxtSchedulerError,"CExampleScheduler - error");
00191         User::Panic(KTxtSchedulerError,aError);
00192         }
00193 
00194 void CExampleScheduler::WaitForAnyRequest()
00195         {
00196         if (!(iActiveConsole->IsActive()))
00197                 iActiveConsole->RequestCharacter();     
00198         CActiveScheduler::WaitForAnyRequest();
00199         }
00200 
00201 void CExampleScheduler::SetActiveObject(CActiveConsole* aActiveConsole)
00202         {
00203         iActiveConsole = aActiveConsole;
00204         }
00205 
00206 
00208 // CFibonacciApplication support routine
00209 //   uses up arrow & down arrow to change number, Enter to select
00211 
00212 TInt GetValueFromKeyboard (TInt aInitial, TInt aStep, TInt lowerLimit, TInt upperLimit, const TDesC& aPrompt, CConsoleBase* aConsole)
00213         {
00214         TChar input ;
00215         TInt value = aInitial ;
00216 
00217         aConsole->Printf(aPrompt) ;
00218         do
00219                 {
00220                 aConsole->SetPos(0);
00221                 _LIT(KFormat1,"%d  ");
00222                 aConsole->Printf(KFormat1, value);
00223                 input = aConsole->Getch() ;
00224                 if (input == EKeyUpArrow && value < upperLimit) value = value + aStep ;
00225                 if (input == EKeyDownArrow && value > lowerLimit) value = value - aStep ;
00226                 if (input == 'c') value = -1;
00227                 }
00228         while (input != EKeyEnter && input != 'c') ;
00229 
00230         return value ;
00231         }
00232 
00233 
00235 //
00236 // -----> CFibonacciApplication (implementation)
00237 //
00239 
00240 CFibonacciApplication::CFibonacciApplication(CConsoleBase* aConsole )
00241         : CActiveConsole(aConsole)
00242           // construct zero-priority active object
00243         {
00244         iConsole = aConsole ;
00245         __DECLARE_NAME(_S("CFibonacciApplication"));
00246         } 
00247 
00248 
00249 CFibonacciApplication* CFibonacciApplication::NewLC(CConsoleBase* aConsole )
00250         {
00251         CFibonacciApplication* self=new (ELeave) CFibonacciApplication(aConsole);
00252         CleanupStack::PushL(self);
00253         self->ConstructL();
00254         return self;
00255         }
00256 
00257 
00258 void CFibonacciApplication::ConstructL()
00259         {
00260           // Add to active scheduler
00261         CActiveScheduler::Add(this);
00262           // Make this the active object
00263         ((CExampleScheduler*)(CActiveScheduler::Current()))->SetActiveObject(this);
00264         }
00265 
00266 
00267 void CFibonacciApplication::ProcessKeyPress(TChar aChar)
00268         {
00269           // if key is ESC 
00270           //   cancel any outstanding request
00271           //   stop the scheduler
00272         if (aChar == EKeyEscape)
00273                 {
00274                 CActiveScheduler::Stop();
00275                 return;
00276                 }
00277 
00278           // If key is "f" or "F"
00279           //   cancel any outstanding request
00280           //   issue a fibonacci request.
00281         if (aChar == 'f' || aChar == 'F') 
00282                 {
00283                 _LIT(KTxtStartingFibonacci,"\nStarting Fibonacci....  \n");
00284                 _LIT(KTxtReturnTermNumber,"\nENTER selects number, and starts calculation\nUP    arrow increases num\nDOWN  arrow decreases num\nC     cancels\n\n");
00285                 _LIT(KTxtCalculating,"\nCalculating...\n");
00286                 _LIT(KFormat2,"\nResult : %u \n");
00287                 _LIT(KTxtCancelled,"Cancelled");
00288 
00289                 iConsole->Printf(KTxtStartingFibonacci);
00290                 
00291                 TInt iterations = GetValueFromKeyboard(5,1,2,46, KTxtReturnTermNumber, iConsole) ;
00292                 if (iterations == -1)  // convenient if awkward but allows us to indicate a request to cancel.
00293                         {
00294                         iConsole->Printf(KTxtCancelled);
00295                         iConsole->Printf(KTxtMainInstructions);
00296                         return;
00297                         }
00298 
00299                 iConsole->Printf(KTxtCalculating);
00300                 iFibonacciEngine.Calculate(iterations);
00301                 
00302                 iConsole->Printf(KFormat2, iFibonacciEngine.iResult) ;
00303                 iConsole->Printf(KTxtMainInstructions);
00304                 return;
00305                 }
00306 
00307        // any other key ignore
00308         _LIT(KTxtNotRecognised,"\nUnwanted key pressed");
00309         iConsole->Printf(KTxtNotRecognised);
00310         iConsole->Printf(KTxtMainInstructions);
00311         }
00312 
00314 //
00315 // -----> TFibonacciEngine (implementation)
00316 //
00318 
00319 void TFibonacciEngine::Calculate (TInt aTerms) 
00320         {
00321         TInt iterations = aTerms ;
00322 
00323         TInt currentTotal = 1 ;
00324         TInt previousTotal = 0 ;
00325         _LIT(KTxtTooManyIterations,"Too many iterations");
00326         __ASSERT_ALWAYS(iterations<47,User::Panic(KTxtTooManyIterations,iterations));
00327 
00328         // if limit not yet reached
00329         while (iterations-- > 0)        
00330                 {
00331                 // calculate next number in series
00332                 TInt newTotal = currentTotal + previousTotal ;
00333 
00334                 // update variables
00335                 previousTotal = currentTotal ;
00336                 currentTotal = newTotal ;
00337 
00338                 // introduce a delay
00339                 User::After(1000000) ;
00340                 }  
00341 
00342         iResult = currentTotal ;
00343 
00344         } 
00345 
00346 
00348 // This section deals with initialisation and ensuring we have a console active
00350 
00351 void doExampleL () ;
00352 
00353 void SetupConsoleL();
00354 
00355 GLDEF_C TInt E32Main()                          // main function called by E32
00356     {
00357         CTrapCleanup* cleanup=CTrapCleanup::New();              // get clean-up stack
00358         TRAPD(error,SetupConsoleL());                                   // more initialization, then do example
00359         _LIT(KTxtFibonacciExampleError,"Fibonacci example error");
00360         __ASSERT_ALWAYS(!error,User::Panic(KTxtFibonacciExampleError,error));
00361         delete cleanup;                                                                 // destroy clean-up stack
00362         return 0;                                                                               // and return
00363     }
00364 
00365 void SetupConsoleL()                             // initialize and call example code under cleanup stack
00366     {
00367         _LIT(KTxtFibSingActObj,"Single Active Object");
00368         console=Console::NewL(KTxtFibSingActObj, TSize(KConsFullScreen,KConsFullScreen));
00369         CleanupStack::PushL(console);
00370 
00371         console->Printf(KTxtMainInstructions) ;
00372         TRAPD(error, doExampleL());                                         // perform example function
00373         if (error)
00374                 {
00375                 _LIT(KFormat3,"failed: leave code=%d");
00376                 console->Printf(KFormat3, error);
00377                 }
00378         _LIT(KTxtPressAnyKey,"[Press any key to exit]");
00379         console->Printf(KTxtPressAnyKey);
00380         console->Getch();                                                               // get and ignore character
00381         CleanupStack::PopAndDestroy();                                  // close console
00382     }
00383 
00384 
00386 //
00387 // Do the example
00388 //
00390 void doExampleL()
00391     {
00392           // Construct and install the active scheduler
00393         CExampleScheduler*  exampleScheduler = new (ELeave) CExampleScheduler;
00394 
00395           // Push onto the cleanup stack
00396         CleanupStack::PushL(exampleScheduler);
00397          
00398           // Install as the active scheduler
00399         CActiveScheduler::Install(exampleScheduler);
00400 
00401           // Create CFibonacciApplication active object.
00402         CFibonacciApplication* fibonacci = CFibonacciApplication::NewLC(console);
00403 
00404           // issue initial request
00405         fibonacci->RequestCharacter() ;
00406                         
00407         // Main part of the program:
00408         //    wait loop that cycles until ActiveScheduler::Stop called
00409         CActiveScheduler::Start();
00410 
00411         // Remove from the cleanup stack and destroy:
00412         // 1. the CFibonacciApplication active object.
00413         // 2. exampleScheduler
00414         CleanupStack::PopAndDestroy(); 
00415         CleanupStack::PopAndDestroy(); 
00416         }
00417 

Generated by  doxygen 1.6.2