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

Generated by  doxygen 1.6.2