diff -r f345bda72bc4 -r 43e37759235e Symbian3/Examples/guid-6013a680-57f9-415b-8851-c4fa63356636/_fibonacci3_8cpp-source.html --- a/Symbian3/Examples/guid-6013a680-57f9-415b-8851-c4fa63356636/_fibonacci3_8cpp-source.html Tue Mar 30 11:56:28 2010 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,537 +0,0 @@ - -
-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 -