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 @@ + + +
+ +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 } +