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