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
Copyright ©2010 Nokia Corporation and/or its subsidiary(-ies).
All rights
reserved. Unless otherwise stated, these materials are provided under the terms of the Eclipse Public License
v1.0.