diff -r f345bda72bc4 -r 43e37759235e Symbian3/Examples/guid-6013a680-57f9-415b-8851-c4fa63356636/threadengine_8cpp_source.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Symbian3/Examples/guid-6013a680-57f9-415b-8851-c4fa63356636/threadengine_8cpp_source.html Tue Mar 30 16:16:55 2010 +0100 @@ -0,0 +1,428 @@ + + + + +TB9.2 Example Applications: examples/ForumNokia/ThreadExample/src/threadengine.cpp Source File + + + + + +

examples/ForumNokia/ThreadExample/src/threadengine.cpp

00001 /*
+00002 * ============================================================================
+00003 *  Name     : CThreadEngine from CThreadEngine.h
+00004 *  Part of  : Thread
+00005 *  Created  : 04.02.2005 by Forum Nokia
+00006 *  Version  : 1.0
+00007 *  Copyright: Nokia Corporation
+00008 * ============================================================================
+00009 */
+00010 
+00011 // INCLUDES
+00012 #include "..\inc\threadengine.h"
+00013 #include "threadappview.h"
+00014 #include "threadanimation.h"
+00015 #include <thread.rsg>
+00016 #include <StringLoader.h> 
+00017 
+00018 // time that threads sleep in ThreadFunction
+00019 const TInt KThreadUpdateInterval = 200000;
+00020 
+00021 // resurrect threads after this interval
+00022 const TInt KThreadWatchdogInterval = 5000000;
+00023 
+00024 // ----------------------------------------------------------------------------
+00025 // CThreadEngine::CThreadEngine(void)
+00026 //
+00027 // constructor
+00028 // ----------------------------------------------------------------------------
+00029 CThreadEngine::CThreadEngine(void): CTimer(CActive::EPriorityStandard), iNotSynchonizedCounter(0), 
+00030         iSynchronizedCounter(0), iCreatedThreads(EFalse)
+00031         {
+00032         // Create a mutex for synchronization purpose
+00033         iMutex.CreateLocal();
+00034 
+00035         }
+00036 
+00037 // ----------------------------------------------------------------------------
+00038 // CThreadEngine::~CThreadEngine(void)
+00039 //
+00040 // destructor
+00041 // ----------------------------------------------------------------------------
+00042 CThreadEngine::~CThreadEngine(void)
+00043         {       
+00044         // Kill all threads before closing the handles
+00045         iThreadOne.Kill(KErrNone);
+00046         iThreadTwo.Kill(KErrNone);
+00047         iThreadThree.Kill(KErrNone);
+00048                 
+00049         // Handles should be closed
+00050         iThreadOne.Close();
+00051         iThreadTwo.Close();
+00052         iThreadThree.Close();   
+00053         }
+00054 
+00055 
+00056 CThreadEngine* CThreadEngine::NewL(CThreadAppView* aView)
+00057         {
+00058         CThreadEngine* self = CThreadEngine::NewLC(aView);
+00059         CleanupStack::Pop(self);
+00060         return self;
+00061         }
+00062 
+00063 CThreadEngine* CThreadEngine::NewLC(CThreadAppView* aView)
+00064         {
+00065         CThreadEngine* self = new (ELeave) CThreadEngine;
+00066         CleanupStack::PushL(self);
+00067         self->ConstructL(aView);
+00068         return self;
+00069         }
+00070 
+00071 // Standard EPOC 2nd phase constructor
+00072 void CThreadEngine::ConstructL(CThreadAppView* aView)
+00073         {
+00074         CTimer::ConstructL();
+00075 
+00076         iView = aView;
+00077         CActiveScheduler::Add( this );
+00078         }
+00079 
+00080 // ----------------------------------------------------------------------------
+00081 // CThreadEngine::StartL()
+00082 //
+00083 // Create threads and start Timer that resurrects threads. 
+00084 // ----------------------------------------------------------------------------
+00085 void CThreadEngine::StartL()
+00086         {
+00087         // Create threads only once
+00088         if ( iCreatedThreads == EFalse )
+00089                 {
+00090                 CreateThreadsL();
+00091                 After( KThreadWatchdogInterval );
+00092                 }
+00093         }
+00094 
+00095 // ----------------------------------------------------------------------------
+00096 // CThreadEngine::RunL()
+00097 //
+00098 // Check that all threads are alive, if not then create and resume them again.
+00099 // After resuming, continue the thread animation.
+00100 // Called by the active scheduler when a request completion event occurs.
+00101 // ExitType can be used to check thread state ( killed / panicked / alive )
+00102 // ----------------------------------------------------------------------------
+00103 void CThreadEngine::RunL()
+00104         {
+00105 
+00106         // Has thread one been killed?
+00107         if ( iThreadOne.ExitType() == EExitKill ) 
+00108                 {
+00109                 HBufC* threadWasKilled = StringLoader::LoadLC( R_THREAD1_WAS_KILLED );
+00110                 iView->DrawText( *threadWasKilled );
+00111                 CleanupStack::PopAndDestroy( threadWasKilled );
+00112                 
+00113                 // Closing the handle finalises thread deconstructing. Thread with
+00114                 // same name can be opened aftewards. Without closing the handle new unique
+00115                 // name must be used. 
+00116                 iThreadOne.Close();
+00117 
+00118                 // Create a new thread because earlier was killed
+00119                 if ( iThreadOne.Create( _L("thread1"), ExecuteThreadOne, 4096, KMinHeapSize, 
+00120                          256*KMinHeapSize, &iNotSynchonizedCounter) != KErrNone )
+00121                         {
+00122                         // Create failed. This should not happen.
+00123                         HBufC* threadCreateFailureText = StringLoader::LoadLC( R_THREAD1_CREATE_FAILURE );
+00124                         iView->DrawText( *threadCreateFailureText );
+00125                         CleanupStack::PopAndDestroy( threadCreateFailureText);
+00126                         }
+00127                 else 
+00128                         {       
+00129                         // Start newly created thread
+00130                         iThreadOne.Resume();
+00131                         // Start the threadOne animation
+00132                         iView->iAnimationOne->StartAnimationL();
+00133                         }               
+00134                 }
+00135 
+00136         // Has thread two been killed?
+00137         if ( iThreadTwo.ExitType() == EExitKill ) 
+00138                 {
+00139                 HBufC* threadWasKilled = StringLoader::LoadLC( R_THREAD2_WAS_KILLED );
+00140                 iView->DrawText( *threadWasKilled );
+00141                 CleanupStack::PopAndDestroy( threadWasKilled );
+00142 
+00143                 iThreadTwo.Close();
+00144 
+00145                 // Create a new thread because earlier was killed
+00146                 if ( KErrNone != iThreadTwo.Create( _L("thread2") , ExecuteThreadTwo, 4096, KMinHeapSize, 
+00147                          256*KMinHeapSize, this ) )
+00148                         {
+00149                         // Create failed. This should not happen.
+00150                         HBufC* threadCreateFailureText = StringLoader::LoadLC( R_THREAD2_CREATE_FAILURE );
+00151                         iView->DrawText( *threadCreateFailureText );
+00152                         CleanupStack::PopAndDestroy( threadCreateFailureText);
+00153                         }
+00154                 else 
+00155                         {
+00156                         // Start newly created thread
+00157                         iThreadTwo.Resume();
+00158                         iView->iAnimationTwo->StartAnimationL();
+00159                         }
+00160                 }
+00161                 
+00162         // Has thread three been killed?
+00163         if ( iThreadThree.ExitType() == EExitKill ) 
+00164                 {
+00165                 HBufC* threadWasKilled = StringLoader::LoadLC( R_THREAD3_WAS_KILLED );
+00166                 iView->DrawText( *threadWasKilled );
+00167                 CleanupStack::PopAndDestroy( threadWasKilled );
+00168 
+00169                 iThreadThree.Close();
+00170 
+00171                 // Create a new thread because earlier was killed
+00172                 if ( KErrNone != iThreadThree.Create( _L("thread3") , ExecuteThreadThree, 4096, KMinHeapSize, 
+00173                          256*KMinHeapSize, this) ) 
+00174                         {
+00175                         // Create failed. This should not happen.
+00176                         HBufC* threadCreateFailureText = StringLoader::LoadLC( R_THREAD1_CREATE_FAILURE );
+00177                         iView->DrawText( *threadCreateFailureText );
+00178                         CleanupStack::PopAndDestroy( threadCreateFailureText );
+00179                         }
+00180                 else 
+00181                         {
+00182                         // Start newly created thread
+00183                         iThreadThree.Resume();
+00184                         iView->iAnimationThree->StartAnimationL();
+00185                         }
+00186                 }
+00187  
+00188         // Wait for a while and run the same function again 
+00189         After( KThreadWatchdogInterval );
+00190         }
+00191 
+00192 // ----------------------------------------------------------------------------
+00193 // CThreadEngine::DoCancel()
+00194 //
+00195 // Cancel and stop the timer. 
+00196 // ----------------------------------------------------------------------------
+00197 void CThreadEngine::DoCancel()
+00198         {
+00199         Cancel();
+00200         }
+00201 
+00202 // ----------------------------------------------------------------------------
+00203 // CThreadEngine::RunError(TInt)
+00204 //
+00205 // Cancel and stop the timer. 
+00206 // ----------------------------------------------------------------------------
+00207 TInt CThreadEngine::RunError(TInt)
+00208         {
+00209         return KErrNone;
+00210         }
+00211 
+00212 // ----------------------------------------------------------------------------
+00213 // CThreadEngine::ThreadKilledText(const TDesC& aText, TInt aCount)
+00214 //
+00215 // Print text and a number after thread has been killed. Count reflects 
+00216 // how long thread was running. TempValue is needed for TInt to TDesC 
+00217 // conversion
+00218 // ----------------------------------------------------------------------------
+00219 void CThreadEngine::ThreadKilledText(const TDesC& aText, TInt aCount)
+00220         {
+00221         TBuf<50> tempBuf;
+00222 
+00223         tempBuf.Append( aText );
+00224         tempBuf.AppendNum( aCount );
+00225         iView->DrawText( tempBuf );     
+00226         }
+00227 
+00228 // ----------------------------------------------------------------------------
+00229 // CThreadEngine::KillThread(TInt aThreadCount)
+00230 //
+00231 // Kill threadOne (1) / threadTwo (2) / threadThree (3)
+00232 // and draw text that a thread has been killed. Stops animation
+00233 // after killing. Resets counters.
+00234 // ----------------------------------------------------------------------------
+00235 void CThreadEngine::KillThread(TInt aThreadCount)
+00236         {
+00237         //Do not kill before threads have been created
+00238         if ( iCreatedThreads == EFalse )
+00239                 {
+00240                 return;
+00241                 }
+00242 
+00243         HBufC* killedText;
+00244 
+00245         switch( aThreadCount )
+00246                 {
+00247                 case 1:
+00248                         // Thread can be killed because handle is connected to it.
+00249                         iThreadOne.Kill(KErrNone);
+00250 
+00251                         killedText = StringLoader::LoadLC(R_KILLED_THREAD1);
+00252                         ThreadKilledText( *killedText, iNotSynchonizedCounter);
+00253                         CleanupStack::PopAndDestroy(killedText);
+00254 
+00255                         iNotSynchonizedCounter = 0;
+00256 
+00257                         iView->iAnimationOne->StopAnimation();
+00258                         
+00259                 break;
+00260                 case 2:
+00261                         iThreadTwo.Kill(KErrNone);
+00262 
+00263                         killedText = StringLoader::LoadLC(R_KILLED_THREAD2);
+00264                         ThreadKilledText( *killedText, iSynchronizedCounter);
+00265                         CleanupStack::PopAndDestroy(killedText);
+00266 
+00267                         // Reset counter
+00268                         SetSyncValue(0);
+00269                         
+00270                         iView->iAnimationTwo->StopAnimation();
+00271 
+00272                 break;
+00273                 case 3:
+00274                         iThreadThree.Kill(KErrNone);
+00275 
+00276                         killedText = StringLoader::LoadLC(R_KILLED_THREAD3);
+00277                         ThreadKilledText( *killedText, iSynchronizedCounter );
+00278                         CleanupStack::PopAndDestroy( killedText );
+00279 
+00280                         // Reset counter
+00281                         SetSyncValue(0);
+00282                         
+00283                         iView->iAnimationThree->StopAnimation();
+00284                 break;
+00285                 }
+00286         }
+00287 
+00288 // ----------------------------------------------------------------------------
+00289 // CThreadEngine::ExecuteThread(TAny *aPtr)
+00290 //
+00291 // Threadfunction of threadOne. Executed only by threadOne.
+00292 // ----------------------------------------------------------------------------
+00293 TInt CThreadEngine::ExecuteThreadOne(TAny *aPtr)
+00294         {
+00295         // Convert pointer
+00296         TInt* notSync = static_cast<TInt*>(aPtr);
+00297         
+00298         TBool loopConditionOne = ETrue;
+00299         while ( loopConditionOne )
+00300                 {
+00301                 // iNotSynchonizedCounter++, synhronization is not needed because
+00302                 // only this thread changes iNotSynchronizedCount value.
+00303                 *notSync = *notSync + 1;
+00304                 // Wait for a while
+00305                 User::After( KThreadUpdateInterval );
+00306                 }
+00307 
+00308         return KErrNone;
+00309         }
+00310 
+00311 // ----------------------------------------------------------------------------
+00312 // CThreadEngine::ExecuteThreadTwo(TAny *aPtr)
+00313 //
+00314 // Threadfunction of threadTwo. Executed only by threadTwo.
+00315 // ----------------------------------------------------------------------------
+00316 TInt CThreadEngine::ExecuteThreadTwo(TAny *aPtr)
+00317         {
+00318         // Convert pointer
+00319         CThreadEngine* engine = static_cast<CThreadEngine*>(aPtr);
+00320         
+00321         TBool loopConditionTwo = ETrue;
+00322         while ( loopConditionTwo )
+00323                 {
+00324                 // iSynchronizedCounter++;
+00325                 // The counter is not handled directly, because two threads
+00326                 // interact with the same variable. Synchronization is needed.
+00327                 engine->SetSyncValue(engine->GetSyncValue()+1);
+00328                 User::After( KThreadUpdateInterval );
+00329                 }
+00330 
+00331         return KErrNone;
+00332         }
+00333 
+00334 // ----------------------------------------------------------------------------
+00335 // CThreadEngine::ExecuteThreadThree(TAny *aPtr)
+00336 //
+00337 // Threadfunction of threadThree. Executed only by threadThree.
+00338 // ----------------------------------------------------------------------------
+00339 TInt CThreadEngine::ExecuteThreadThree(TAny *aPtr)
+00340         {
+00341         CThreadEngine* engine = static_cast<CThreadEngine*>(aPtr);
+00342 
+00343         TBool loopConditionThree = ETrue;
+00344         while ( loopConditionThree )
+00345                 {
+00346                 // iSynchronizedCounter++;
+00347                 // The counter is not handled directly, because two threads
+00348                 // interact with the same variable. Synchronization is needed.
+00349                 engine->SetSyncValue(engine->GetSyncValue()+1);
+00350                 User::After( KThreadUpdateInterval );
+00351                 }
+00352 
+00353         return KErrNone;
+00354         }
+00355 
+00356 // ----------------------------------------------------------------------------
+00357 // CThreadEngine::SetSyncValue(TInt aValue)
+00358 //
+00359 // Set the iSynchronizedCounter value. Synchronization is implemented by using
+00360 // a semaphore. Function is thread-safe.
+00361 // ----------------------------------------------------------------------------
+00362 void CThreadEngine::SetSyncValue(TInt aValue)
+00363         {
+00364         iMutex.Wait();
+00365         iSynchronizedCounter = aValue;
+00366         iMutex.Signal();
+00367         }
+00368 
+00369 // ----------------------------------------------------------------------------
+00370 // CThreadEngine::GetSyncValue() const
+00371 //
+00372 // Returns iSynchronizedCounter. 
+00373 // 
+00374 // ----------------------------------------------------------------------------
+00375 TInt CThreadEngine::GetSyncValue() const
+00376         {
+00377         return iSynchronizedCounter;
+00378         }
+00379 
+00380 // ----------------------------------------------------------------------------
+00381 // CThreadEngine::CreateThreadsL()
+00382 //
+00383 // Create three threads and resume them. Start thread animations.
+00384 // 
+00385 // ----------------------------------------------------------------------------
+00386 void CThreadEngine::CreateThreadsL()
+00387         {
+00388         //Create thread1
+00389         iThreadOne.Create( _L("thread1") , ExecuteThreadOne, 4096, KMinHeapSize, 256*KMinHeapSize, 
+00390                 &iNotSynchonizedCounter);
+00391         iThreadOne.Resume();
+00392         iView->iAnimationOne->StartAnimationL();
+00393 
+00394         // Create thread2
+00395         // thread two and three modify same counter, that is why a pointer to this class is given,
+00396         // not the counter itself. Threads modify iSynchronizedCounter through two CThreadEngine 
+00397         // functions: GetSyncValue() / SetSyncValue(). Thread2 gets a pointer to CThreadEngine,
+00398         // because it must use synchronized funtions to increment the counter.
+00399         iThreadTwo.Create( _L("thread2") , ExecuteThreadTwo, 4096, KMinHeapSize, 256*KMinHeapSize,
+00400                 this);  
+00401         iThreadTwo.Resume();
+00402         iView->iAnimationTwo->StartAnimationL();
+00403 
+00404         //Create thread3
+00405         iThreadThree.Create(_L("thread3") , ExecuteThreadThree, 4096, KMinHeapSize, 256*KMinHeapSize,
+00406                 this );
+00407         iThreadThree.Resume();
+00408         iView->iAnimationThree->StartAnimationL();
+00409 
+00410         // All threads have been now created. Threads can be killed.
+00411         iCreatedThreads = ETrue;        
+00412         }
+
+
Generated by  + +doxygen 1.6.2
+ +