diff -r f345bda72bc4 -r 43e37759235e Symbian3/Examples/guid-6013a680-57f9-415b-8851-c4fa63356636/_fibonacci3_8cpp_source.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Symbian3/Examples/guid-6013a680-57f9-415b-8851-c4fa63356636/_fibonacci3_8cpp_source.html Tue Mar 30 16:16:55 2010 +0100 @@ -0,0 +1,541 @@ + + +
+ +00001 // Copyright (c) 1997-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 as a background active object. +00016 // The technique used is similar to, but not identical, to that used by CIdle, where +00017 // the background active object is repeatedly called provided the other (higher priority) +00018 // active objects are not ready to run. +00019 // Fibonacci Active Objects example +00020 // +00021 +00022 #include <e32cons.h> +00023 #include <e32base.h> +00024 #include <e32std.h> +00025 +00027 //nclude <e32hal.h> +00028 +00029 +00030 LOCAL_D CConsoleBase* console; +00031 +00032 _LIT(KTxtMainInstructions,"\n\nPress 'F' to start\n 'ESC' to exit\n 'C' to cancel, anytime\n"); +00033 +00035 // +00036 // -----> CActiveConsole (definition) +00037 // +00038 // An abstract class which provides the facility to issue key requests. +00039 // +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 class CActiveConsole; +00080 +00081 class CExampleScheduler : public CActiveScheduler +00082 { +00083 public: +00084 void Error (TInt aError) const; +00085 void WaitForAnyRequest(); +00086 void SetActiveObject(CActiveConsole* aActiveConsole); +00087 private: +00088 // data members defined for this class +00089 CActiveConsole* iActiveConsole; +00090 }; +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 CFibonacciEngine() ; +00106 void StartCalculate (TInt aTerms) ; +00107 void StepCalculate () ; +00108 +00109 TUint iResult ; +00110 +00111 enum TEngineState {eInactive, eCalculating, eCompleted} ; +00112 TEngineState iState ; +00113 +00114 private: +00115 TUint iCurrentTotal ; +00116 TUint iPreviousTotal ; +00117 TInt iTermsLeftToDo ; +00118 } ; +00119 +00120 +00122 // +00123 // -----> CFibonacciApplication (definition) +00124 // +00125 // This class encapsulates the fibonacci thread that runs the fibonacci engine +00126 // +00128 +00129 class CFibonacciApplication : public CActive +00130 { +00131 public: +00132 CFibonacciApplication(CConsoleBase* aConsole, CFibonacciEngine* aFibonacciEngine) ; +00133 ~CFibonacciApplication() ; +00134 +00135 void CalculateFibonacci(TInt aIterations) ; +00136 +00137 private: +00138 void DoCancel() ; +00139 void RunL() ; +00140 +00141 private: +00142 CConsoleBase* iConsole ; +00143 CFibonacciEngine* iFibonacciEngine ; +00144 } ; +00145 +00146 +00148 // +00149 // -----> CFibonacciKeyHandler (definition) +00150 // +00151 // This class encapsulates the fibonacci keyboard handler +00152 // +00154 +00155 class CFibonacciKeyHandler : public CActiveConsole +00156 { +00157 public: +00158 CFibonacciKeyHandler( CConsoleBase* aConsole, +00159 CFibonacciApplication* aApplication) ; +00160 void ConstructL(); +00161 +00162 // Static construction +00163 static CFibonacciKeyHandler* NewLC(CConsoleBase* aConsole, CFibonacciApplication* aHandler) ; +00164 +00165 // service request +00166 void ProcessKeyPress(TChar aChar) ; +00167 +00168 private: +00169 CConsoleBase* iConsole ; +00170 CFibonacciApplication* iApplication ; +00171 }; +00172 +00173 +00175 // +00176 // -----> CActiveConsole (implementation) +00177 // +00179 CActiveConsole::CActiveConsole( CConsoleBase* aConsole) +00180 : CActive(CActive::EPriorityUserInput) +00181 // Construct high-priority active object +00182 { +00183 iConsole = aConsole; +00184 __DECLARE_NAME(_S("CActiveConsole")); +00185 +00186 } +00187 +00188 void CActiveConsole::ConstructL() +00189 { +00190 // Add to active scheduler +00191 CActiveScheduler::Add(this); +00192 } +00193 +00194 CActiveConsole::~CActiveConsole() +00195 { +00196 // Make sure we're cancelled +00197 Cancel(); +00198 } +00199 +00200 void CActiveConsole::DoCancel() +00201 { +00202 iConsole->ReadCancel(); +00203 } +00204 +00205 void CActiveConsole::RunL() +00206 { +00207 // Handle completed request +00208 ProcessKeyPress(TChar(iConsole->KeyCode())); +00209 } +00210 +00211 void CActiveConsole::RequestCharacter() +00212 { +00213 // A request is issued to the CConsoleBase to accept a +00214 // character from the keyboard. +00215 iConsole->Read(iStatus); +00216 SetActive(); +00217 } +00218 +00219 +00221 // +00222 // -----> CExampleScheduler (implementation) +00223 // +00225 void CExampleScheduler::Error(TInt aError) const +00226 { +00227 _LIT(KTxtSchedulerError,"CExampleScheduler - error"); +00228 User::Panic(KTxtSchedulerError,aError); +00229 } +00230 +00231 +00232 void CExampleScheduler::WaitForAnyRequest() +00233 { +00234 if (!(iActiveConsole->IsActive())) +00235 iActiveConsole->RequestCharacter(); +00236 CActiveScheduler::WaitForAnyRequest(); +00237 } +00238 +00239 void CExampleScheduler::SetActiveObject(CActiveConsole* aActiveConsole) +00240 { +00241 iActiveConsole = aActiveConsole; +00242 } +00243 +00244 +00245 +00247 // CFibonacciKeyHandler support routine +00248 // uses up arrow & down arrow to change number, Enter to select +00250 +00251 TInt GetValueFromKeyboard (TInt aInitial, TInt aStep, TInt lowerLimit, TInt upperLimit, const TDesC& aPrompt, CConsoleBase* aConsole) +00252 { +00253 TChar input ; +00254 TInt value = aInitial ; +00255 +00256 aConsole->Printf(aPrompt) ; +00257 do +00258 { +00259 aConsole->SetPos(0); +00260 _LIT(KFormat1,"%d "); +00261 aConsole->Printf(KFormat1, value); +00262 input = aConsole->Getch() ; +00263 if (input == EKeyUpArrow && value < upperLimit) value = value + aStep ; +00264 if (input == EKeyDownArrow && value > lowerLimit) value = value - aStep ; +00265 } +00266 while (input != EKeyEnter) ; +00267 +00268 return value ; +00269 } +00270 +00271 +00273 // +00274 // -----> CFibonacciKeyHandler (implementation) +00275 // +00277 +00278 CFibonacciKeyHandler::CFibonacciKeyHandler(CConsoleBase* aConsole, CFibonacciApplication* aApplication) +00279 : CActiveConsole(aConsole) +00280 // construct zero-priority active object +00281 { +00282 iConsole = aConsole ; +00283 iApplication = aApplication ; +00284 +00285 __DECLARE_NAME(_S("CFibonacciApplication")); +00286 // Add to active scheduler +00287 CActiveScheduler::Add(this); +00288 // Make this the active object +00289 ((CExampleScheduler*)(CActiveScheduler::Current()))->SetActiveObject(this); +00290 } +00291 +00292 +00293 void CFibonacciKeyHandler::ProcessKeyPress(TChar aChar) +00294 { +00295 // if key is ESC, cancel any outstanding request & stop the scheduler +00296 if (aChar == EKeyEscape) +00297 { +00298 CActiveScheduler::Stop(); +00299 return; +00300 } +00301 +00302 // If key is "f" or "F", issue a Fibonacci request if none is in progress +00303 if (aChar == 'f' || aChar == 'F') +00304 { +00305 if (!(iApplication->IsActive())) +00306 { +00307 _LIT(KTxtReturnTermNumber,"\nENTER selects num\nUP arrow increases num\nDOWN arrow decreases num\n\n"); +00308 TInt iterations = GetValueFromKeyboard(5,1,2,46, KTxtReturnTermNumber, iConsole) ; +00309 iApplication->CalculateFibonacci(iterations); +00310 } +00311 else +00312 { +00313 _LIT(KTxtAlreadyInProgress,"[Already in progress]"); +00314 iConsole->Printf(KTxtAlreadyInProgress); +00315 } +00316 return; +00317 } +00318 +00319 // If key is "c" or "C", cancel any outstanding request +00320 if (aChar == 'c' || aChar == 'C') +00321 { +00322 _LIT(KTxtCancelFibonacci,"\nCancelling Fibonacci.... \n"); +00323 iConsole->Printf(KTxtCancelFibonacci); +00324 iApplication->Cancel(); +00325 iConsole->Printf(KTxtMainInstructions); +00326 return; +00327 } +00328 +00329 _LIT(KTxtNotRecognised,"\nUnwanted key pressed"); +00330 iConsole->Printf(KTxtNotRecognised); +00331 iConsole->Printf(KTxtMainInstructions); +00332 } +00333 +00334 +00336 // +00337 // -----> CFibonacciApplication (implementation) +00338 // +00340 +00341 CFibonacciApplication::CFibonacciApplication(CConsoleBase* aConsole, CFibonacciEngine* aFibonacciEngine) +00342 // +00343 // Constructor +00344 // +00345 : CActive(EPriorityStandard) +00346 { +00347 iConsole = aConsole ; +00348 iFibonacciEngine = aFibonacciEngine ; +00349 CActiveScheduler::Add(this); +00350 __DECLARE_NAME(_S("CFibonacciApplication")); +00351 }; +00352 +00353 +00354 // destructor +00355 CFibonacciApplication::~CFibonacciApplication() +00356 { +00357 // cancel any requests and tell server +00358 Cancel() ; +00359 } +00360 +00361 +00362 void CFibonacciApplication::DoCancel() +00363 { +00364 // cancel the active object request +00365 iFibonacciEngine->iState = CFibonacciEngine::eInactive ; +00366 } +00367 +00368 +00369 +00370 // initiate a request +00371 void CFibonacciApplication::CalculateFibonacci(TInt aIterations) +00372 { +00373 // initialize engine +00374 // no neeed to set iStatus to KRequestPending, as request completes below +00375 iFibonacciEngine->StartCalculate(aIterations) ; +00376 +00377 // schedule the request +00378 SetActive() ; +00379 +00380 // send signal that this request has completed +00381 TRequestStatus* status = &iStatus ; +00382 User::RequestComplete(status, KErrNone) ; +00383 } +00384 +00385 +00386 +00387 void CFibonacciApplication::RunL() +00388 // implements a simple state engine: {eInactive, eCalculating, eCompleted} +00389 { +00390 if (iFibonacciEngine->iState == CFibonacciEngine::eInactive ) +00391 { +00392 _LIT(KTxtEngineNotInitialized,"Engine not initialized"); +00393 User::Panic(KTxtEngineNotInitialized, KErrNotReady) ; +00394 } +00395 else if (iFibonacciEngine->iState == CFibonacciEngine::eCalculating ) +00396 { +00397 // unnecessary - just provides feedback on progression of the calculation +00398 _LIT(KTxtDot,"."); +00399 iConsole->Printf(KTxtDot) ; +00400 +00401 // no neeed to set iStatus to KRequestPending, as request completes below +00402 +00403 // request next step +00404 iFibonacciEngine->StepCalculate() ; +00405 +00406 // schedule request +00407 SetActive() ; +00408 +00409 // send signal that this request has completed +00410 TRequestStatus* status = &iStatus ; +00411 User::RequestComplete(status, KErrNone) ; +00412 } +00413 else if (iFibonacciEngine->iState == CFibonacciEngine::eCompleted ) +00414 { +00415 // finished calculation: print result and reset state engine +00416 _LIT(KFormat2,"\n Result : %u \n"); //not used +00417 iConsole->Printf(KFormat2, iFibonacciEngine->iResult) ; +00418 iConsole->Printf(KTxtMainInstructions) ; +00419 iFibonacciEngine->iState = CFibonacciEngine::eInactive ; +00420 } +00421 } +00422 +00423 +00424 +00426 // +00427 // -----> CFibonacciEngine (implementation) +00428 // +00430 CFibonacciEngine::CFibonacciEngine() +00431 { +00432 iState = eInactive ; +00433 } +00434 +00435 +00436 void CFibonacciEngine::StartCalculate (TInt aTerms) +00437 { +00438 // initialise all internal variables to initial state +00439 iCurrentTotal = 1 ; +00440 iPreviousTotal = 0 ; +00441 iResult = 0 ; +00442 iTermsLeftToDo = aTerms + 1 ; // first step completed in variable initialization +00443 iState = eCalculating ; +00444 } +00445 +00446 +00447 +00448 void CFibonacciEngine::StepCalculate () +00449 { +00450 +00451 // if full calculation not yet complete, but in progress (i.e. not cancelled) +00452 if (--iTermsLeftToDo > 0 && iState == eCalculating) +00453 { +00454 // calculate next number in series +00455 TInt newTotal = iCurrentTotal + iPreviousTotal ; +00456 +00457 // update internal variables +00458 iPreviousTotal = iCurrentTotal ; +00459 iCurrentTotal = newTotal ; +00460 +00461 // introduce a delay to make us a long-running service +00462 User::After(1000000) ; +00463 +00464 // not necessary, but allows running total to be used during the calculation +00465 // (say for putting values into a chart or graph) +00466 iResult = iCurrentTotal ; +00467 } +00468 else if (iTermsLeftToDo <= 0) +00469 { +00470 // flag that calculation has finished and ensure final result is available +00471 iState = eCompleted ; +00472 iResult = iCurrentTotal ; +00473 } +00474 } +00475 +00476 +00477 +00479 // This section deals with initialisation and ensuring we have a console active +00481 +00482 void doExampleL () ; +00483 +00484 void SetupConsoleL(); +00485 +00486 GLDEF_C TInt E32Main() // main function called by E32 +00487 { +00488 CTrapCleanup* cleanup=CTrapCleanup::New(); // get clean-up stack +00489 TRAPD(error,SetupConsoleL()); // more initialization, then do example +00490 _LIT(KTxtFibonacciExampleError,"Fibonacci example error"); +00491 __ASSERT_ALWAYS(!error,User::Panic(KTxtFibonacciExampleError,error)); +00492 delete cleanup; // destroy clean-up stack +00493 return 0; // and return +00494 } +00495 +00496 void SetupConsoleL() // initialize and call example code under cleanup stack +00497 { +00498 _LIT(KTxtFibActObjBackground,"Background Active Object"); +00499 console=Console::NewL(KTxtFibActObjBackground, TSize(KConsFullScreen,KConsFullScreen)); +00500 CleanupStack::PushL(console); +00501 console->Printf(KTxtMainInstructions) ; +00502 TRAPD(error, doExampleL()); // perform example function +00503 if (error) +00504 { +00505 _LIT(KFormat3,"failed: leave code=%d"); +00506 console->Printf(KFormat3, error); +00507 } +00508 _LIT(KTxtPressAnyKey,"[Press any key to exit]"); +00509 console->Printf(KTxtPressAnyKey); +00510 console->Getch(); // get and ignore character +00511 CleanupStack::PopAndDestroy(); // close console +00512 } +00513 +00514 +00516 // +00517 // Do the example +00518 // +00520 void doExampleL() +00521 { +00522 // Construct and install the active scheduler; push onto the cleanup stack +00523 CExampleScheduler* exampleScheduler = new (ELeave) CExampleScheduler; +00524 CleanupStack::PushL(exampleScheduler); +00525 +00526 // Install as the active scheduler +00527 CActiveScheduler::Install(exampleScheduler); +00528 +00529 // Create CFibonacciEngine active object; push onto the cleanup stack +00530 CFibonacciEngine* fibEngine = new (ELeave) CFibonacciEngine ; +00531 CleanupStack::PushL(fibEngine); +00532 +00533 // Create CFibonacciApplication handler active object; push onto the cleanup stack +00534 CFibonacciApplication* fibApplication = new CFibonacciApplication(console, fibEngine); +00535 CleanupStack::PushL(fibApplication); +00536 +00537 // Create CFibonacciKeyHandler active object; push onto the cleanup stack +00538 CFibonacciKeyHandler* fibKeyHandler = new CFibonacciKeyHandler(console, fibApplication); +00539 CleanupStack::PushL(fibKeyHandler); +00540 +00541 // issue initial request +00542 fibKeyHandler->RequestCharacter() ; +00543 +00544 // Main part of the program: +00545 // wait loop that cycles until ActiveScheduler::Stop called +00546 CActiveScheduler::Start(); +00547 +00548 // Remove items from the cleanup stack and destroy them +00549 CleanupStack::PopAndDestroy(4); +00550 } +00551 +00552 +