examples/Base/IPC/Async/Fibonacci1/Fibonacci1.cpp

00001 /*
00002 Copyright (c) 2000-2010 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
00003 
00004 Redistribution and use in source and binary forms, with or without
00005 modification, are permitted provided that the following conditions are met:
00006 
00007 * Redistributions of source code must retain the above copyright notice, this
00008   list of conditions and the following disclaimer.
00009 * Redistributions in binary form must reproduce the above copyright notice,
00010   this list of conditions and the following disclaimer in the documentation
00011   and/or other materials provided with the distribution.
00012 * Neither the name of Nokia Corporation nor the names of its contributors
00013   may be used to endorse or promote products derived from this software
00014   without specific prior written permission.
00015 
00016 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00017 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00018 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00019 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
00020 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00021 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00022 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00023 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00024 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00025 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026 
00027 Description:
00028 Example wraps a console in an active object.
00029 Calculates Fibonacci number as chosen by the user. Note that, in this
00030 example, the calculation is done as part of the console active object's 
00031 RunL() and can take a long time to complete. It also means that nothing
00032 else can happen (including responding to keyboard events) until the 
00033 calculation is complete.   
00034 */
00035 
00036 
00037 
00038 #include <e32base.h>
00039 #include <e32cons.h>
00040 #include <e32std.h>
00041 
00042 
00043 LOCAL_D CConsoleBase* console;
00044 
00045 _LIT(KTxtMainInstructions,"\n\nPress 'F' to start\n      'ESC' to exit.\n");
00046 
00048 //
00049 // -----> CActiveConsole (definition)
00050 //
00051 // An abstract class which provides the facility to issue key requests. 
00052 //
00054 
00055 class CActiveConsole : public CActive
00056         {
00057 public:
00058           // Construction
00059         CActiveConsole(CConsoleBase* aConsole);
00060         void ConstructL();
00061 
00062           // Destruction
00063         ~CActiveConsole();
00064 
00065           // Issue request
00066         void RequestCharacter();
00067         
00068           // Cancel request.
00069           // Defined as pure virtual by CActive;
00070           // implementation provided by this class.
00071         void DoCancel();
00072 
00073           // Service completed request.
00074           // Defined as pure virtual by CActive;
00075           // implementation provided by this class,
00076         void RunL();
00077 
00078           // Called from RunL() - an implementation must be provided
00079           // by derived classes to handle the completed request
00080         virtual void ProcessKeyPress(TChar aChar) = 0; 
00081           
00082 protected:
00083           // Data members defined by this class
00084         CConsoleBase* iConsole; // A console for reading from
00085         };
00086 
00087 
00089 //
00090 // -----> CExampleScheduler (definition)
00091 //
00093 
00094 class CExampleScheduler : public CActiveScheduler
00095         {
00096 public:
00097         void Error (TInt aError) const;
00098         void WaitForAnyRequest();
00099         void SetActiveObject(CActiveConsole* aActiveConsole);
00100 private:
00101           // data members defined for this class
00102         CActiveConsole* iActiveConsole;
00103         };
00104 
00105 
00107 //
00108 // -----> TFibonacciEngine (definition)
00109 //
00110 // This class provides the fibonacci calculation engine
00111 //
00113 
00114 class TFibonacciEngine
00115         {
00116 public:
00117         void Calculate (TInt aTerms) ;
00118 
00119         TInt iResult ;
00120         } ;
00121 
00122 
00124 //
00125 // -----> CFibonacciApplication (definition)
00126 //
00127 // This class encapsulates the fibonacci calculation engine
00128 //
00130 
00131 class CFibonacciApplication : public CActiveConsole
00132         {
00133 public:
00134         CFibonacciApplication(CConsoleBase* aConsole) ;
00135         void ConstructL();
00136 
00137           // Static construction
00138         static CFibonacciApplication* NewLC(CConsoleBase* aConsole) ;
00139 
00140           // service request
00141         void ProcessKeyPress(TChar aChar) ;
00142 
00143 private:
00144         CConsoleBase* iConsole ;
00145         TFibonacciEngine iFibonacciEngine ;
00146         };
00147 
00148 
00150 //
00151 // -----> CActiveConsole (implementation)
00152 //
00154 
00155 CActiveConsole::CActiveConsole( CConsoleBase* aConsole) 
00156         : CActive(CActive::EPriorityUserInput)
00157           // Construct high-priority active object
00158         {
00159         iConsole = aConsole;
00160         __DECLARE_NAME(_S("CActiveConsole"));
00161 
00162         }
00163 
00164 void CActiveConsole::ConstructL()
00165         {
00166           // Add to active scheduler
00167         CActiveScheduler::Add(this);
00168         }
00169 
00170 CActiveConsole::~CActiveConsole()
00171         {
00172         // Make sure we're cancelled
00173         Cancel();
00174         }
00175 
00176 void  CActiveConsole::DoCancel()
00177         {
00178         iConsole->ReadCancel();
00179         }
00180 
00181 void  CActiveConsole::RunL()
00182         {
00183           // Handle completed request
00184         ProcessKeyPress(TChar(iConsole->KeyCode()));
00185         }
00186 
00187 void CActiveConsole::RequestCharacter()
00188         {
00189           // A request is issued to the CConsoleBase to accept a
00190           // character from the keyboard.
00191         iConsole->Read(iStatus); 
00192         SetActive();
00193         }
00194 
00195 
00197 //
00198 // -----> CExampleScheduler (implementation)
00199 //
00201 
00202 void CExampleScheduler::Error(TInt aError) const
00203         {
00204         _LIT(KTxtSchedulerError,"CExampleScheduler - error");
00205         User::Panic(KTxtSchedulerError,aError);
00206         }
00207 
00208 void CExampleScheduler::WaitForAnyRequest()
00209         {
00210         if (!(iActiveConsole->IsActive()))
00211                 iActiveConsole->RequestCharacter();     
00212         CActiveScheduler::WaitForAnyRequest();
00213         }
00214 
00215 void CExampleScheduler::SetActiveObject(CActiveConsole* aActiveConsole)
00216         {
00217         iActiveConsole = aActiveConsole;
00218         }
00219 
00220 
00222 // CFibonacciApplication support routine
00223 //   uses up arrow & down arrow to change number, Enter to select
00225 
00226 TInt GetValueFromKeyboard (TInt aInitial, TInt aStep, TInt lowerLimit, TInt upperLimit, const TDesC& aPrompt, CConsoleBase* aConsole)
00227         {
00228         TChar input ;
00229         TInt value = aInitial ;
00230 
00231         aConsole->Printf(aPrompt) ;
00232         do
00233                 {
00234                 aConsole->SetPos(0);
00235                 _LIT(KFormat1,"%d  ");
00236                 aConsole->Printf(KFormat1, value);
00237                 input = aConsole->Getch() ;
00238                 if (input == EKeyUpArrow && value < upperLimit) value = value + aStep ;
00239                 if (input == EKeyDownArrow && value > lowerLimit) value = value - aStep ;
00240                 if (input == 'c') value = -1;
00241                 }
00242         while (input != EKeyEnter && input != 'c') ;
00243 
00244         return value ;
00245         }
00246 
00247 
00249 //
00250 // -----> CFibonacciApplication (implementation)
00251 //
00253 
00254 CFibonacciApplication::CFibonacciApplication(CConsoleBase* aConsole )
00255         : CActiveConsole(aConsole)
00256           // construct zero-priority active object
00257         {
00258         iConsole = aConsole ;
00259         __DECLARE_NAME(_S("CFibonacciApplication"));
00260         } 
00261 
00262 
00263 CFibonacciApplication* CFibonacciApplication::NewLC(CConsoleBase* aConsole )
00264         {
00265         CFibonacciApplication* self=new (ELeave) CFibonacciApplication(aConsole);
00266         CleanupStack::PushL(self);
00267         self->ConstructL();
00268         return self;
00269         }
00270 
00271 
00272 void CFibonacciApplication::ConstructL()
00273         {
00274           // Add to active scheduler
00275         CActiveScheduler::Add(this);
00276           // Make this the active object
00277         ((CExampleScheduler*)(CActiveScheduler::Current()))->SetActiveObject(this);
00278         }
00279 
00280 
00281 void CFibonacciApplication::ProcessKeyPress(TChar aChar)
00282         {
00283           // if key is ESC 
00284           //   cancel any outstanding request
00285           //   stop the scheduler
00286         if (aChar == EKeyEscape)
00287                 {
00288                 CActiveScheduler::Stop();
00289                 return;
00290                 }
00291 
00292           // If key is "f" or "F"
00293           //   cancel any outstanding request
00294           //   issue a fibonacci request.
00295         if (aChar == 'f' || aChar == 'F') 
00296                 {
00297                 _LIT(KTxtStartingFibonacci,"\nStarting Fibonacci....  \n");
00298                 _LIT(KTxtReturnTermNumber,"\nENTER selects number, and starts calculation\nUP    arrow increases num\nDOWN  arrow decreases num\nC     cancels\n\n");
00299                 _LIT(KTxtCalculating,"\nCalculating...\n");
00300                 _LIT(KFormat2,"\nResult : %u \n");
00301                 _LIT(KTxtCancelled,"Cancelled");
00302 
00303                 iConsole->Printf(KTxtStartingFibonacci);
00304                 
00305                 TInt iterations = GetValueFromKeyboard(5,1,2,46, KTxtReturnTermNumber, iConsole) ;
00306                 if (iterations == -1)  // convenient if awkward but allows us to indicate a request to cancel.
00307                         {
00308                         iConsole->Printf(KTxtCancelled);
00309                         iConsole->Printf(KTxtMainInstructions);
00310                         return;
00311                         }
00312 
00313                 iConsole->Printf(KTxtCalculating);
00314                 iFibonacciEngine.Calculate(iterations);
00315                 
00316                 iConsole->Printf(KFormat2, iFibonacciEngine.iResult) ;
00317                 iConsole->Printf(KTxtMainInstructions);
00318                 return;
00319                 }
00320 
00321        // any other key ignore
00322         _LIT(KTxtNotRecognised,"\nUnwanted key pressed");
00323         iConsole->Printf(KTxtNotRecognised);
00324         iConsole->Printf(KTxtMainInstructions);
00325         }
00326 
00328 //
00329 // -----> TFibonacciEngine (implementation)
00330 //
00332 
00333 void TFibonacciEngine::Calculate (TInt aTerms) 
00334         {
00335         TInt iterations = aTerms ;
00336 
00337         TInt currentTotal = 1 ;
00338         TInt previousTotal = 0 ;
00339         _LIT(KTxtTooManyIterations,"Too many iterations");
00340         __ASSERT_ALWAYS(iterations<47,User::Panic(KTxtTooManyIterations,iterations));
00341 
00342         // if limit not yet reached
00343         while (iterations-- > 0)        
00344                 {
00345                 // calculate next number in series
00346                 TInt newTotal = currentTotal + previousTotal ;
00347 
00348                 // update variables
00349                 previousTotal = currentTotal ;
00350                 currentTotal = newTotal ;
00351 
00352                 // introduce a delay
00353                 User::After(1000000) ;
00354                 }  
00355 
00356         iResult = currentTotal ;
00357 
00358         } 
00359 
00360 
00362 // This section deals with initialisation and ensuring we have a console active
00364 
00365 void doExampleL () ;
00366 
00367 void SetupConsoleL();
00368 
00369 GLDEF_C TInt E32Main()                          // main function called by E32
00370     {
00371         CTrapCleanup* cleanup=CTrapCleanup::New();              // get clean-up stack
00372         TRAPD(error,SetupConsoleL());                                   // more initialization, then do example
00373         _LIT(KTxtFibonacciExampleError,"Fibonacci example error");
00374         __ASSERT_ALWAYS(!error,User::Panic(KTxtFibonacciExampleError,error));
00375         delete cleanup;                                                                 // destroy clean-up stack
00376         return 0;                                                                               // and return
00377     }
00378 
00379 void SetupConsoleL()                             // initialize and call example code under cleanup stack
00380     {
00381         _LIT(KTxtFibSingActObj,"Single Active Object");
00382         console=Console::NewL(KTxtFibSingActObj, TSize(KConsFullScreen,KConsFullScreen));
00383         CleanupStack::PushL(console);
00384 
00385         console->Printf(KTxtMainInstructions) ;
00386         TRAPD(error, doExampleL());                                         // perform example function
00387         if (error)
00388                 {
00389                 _LIT(KFormat3,"failed: leave code=%d");
00390                 console->Printf(KFormat3, error);
00391                 }
00392         _LIT(KTxtPressAnyKey,"[Press any key to exit]");
00393         console->Printf(KTxtPressAnyKey);
00394         console->Getch();                                                               // get and ignore character
00395         CleanupStack::PopAndDestroy();                                  // close console
00396     }
00397 
00398 
00400 //
00401 // Do the example
00402 //
00404 void doExampleL()
00405     {
00406           // Construct and install the active scheduler
00407         CExampleScheduler*  exampleScheduler = new (ELeave) CExampleScheduler;
00408 
00409           // Push onto the cleanup stack
00410         CleanupStack::PushL(exampleScheduler);
00411          
00412           // Install as the active scheduler
00413         CActiveScheduler::Install(exampleScheduler);
00414 
00415           // Create CFibonacciApplication active object.
00416         CFibonacciApplication* fibonacci = CFibonacciApplication::NewLC(console);
00417 
00418           // issue initial request
00419         fibonacci->RequestCharacter() ;
00420                         
00421         // Main part of the program:
00422         //    wait loop that cycles until ActiveScheduler::Stop called
00423         CActiveScheduler::Start();
00424 
00425         // Remove from the cleanup stack and destroy:
00426         // 1. the CFibonacciApplication active object.
00427         // 2. exampleScheduler
00428         CleanupStack::PopAndDestroy(); 
00429         CleanupStack::PopAndDestroy(); 
00430         }
00431 

Generated by  doxygen 1.6.2