⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 threadengine.cpp

📁 这是Symbian平台实现多线程的实例.对初学者非常有帮助.
💻 CPP
字号:
/*
* ============================================================================
*  Name     : CThreadEngine from CThreadEngine.h
*  Part of  : Thread
*  Created  : 04.02.2005 by Forum Nokia
*  Version  : 1.0
*  Copyright: Nokia Corporation
* ============================================================================
*/

// INCLUDES
#include "..\inc\threadengine.h"
#include "threadappview.h"
#include "threadanimation.h"
#include <thread.rsg>
#include <StringLoader.h> 

// time that threads sleep in ThreadFunction
const TInt KThreadUpdateInterval = 200000;

// resurrect threads after this interval
const TInt KThreadWatchdogInterval = 5000000;

// ----------------------------------------------------------------------------
// CThreadEngine::CThreadEngine(void)
//
// constructor
// ----------------------------------------------------------------------------
CThreadEngine::CThreadEngine(void): CTimer(CActive::EPriorityStandard), iNotSynchonizedCounter(0), 
	iSynchronizedCounter(0), iCreatedThreads(EFalse)
	{
	// Create a mutex for synchronization purpose
	iMutex.CreateLocal();

	}

// ----------------------------------------------------------------------------
// CThreadEngine::~CThreadEngine(void)
//
// destructor
// ----------------------------------------------------------------------------
CThreadEngine::~CThreadEngine(void)
	{	
	// Kill all threads before closing the handles
	iThreadOne.Kill(KErrNone);
	iThreadTwo.Kill(KErrNone);
	iThreadThree.Kill(KErrNone);
		
	// Handles should be closed
	iThreadOne.Close();
	iThreadTwo.Close();
	iThreadThree.Close();	
	}


CThreadEngine* CThreadEngine::NewL(CThreadAppView* aView)
	{
	CThreadEngine* self = CThreadEngine::NewLC(aView);
	CleanupStack::Pop(self);
	return self;
	}

CThreadEngine* CThreadEngine::NewLC(CThreadAppView* aView)
	{
	CThreadEngine* self = new (ELeave) CThreadEngine;
	CleanupStack::PushL(self);
	self->ConstructL(aView);
	return self;
	}

// Standard EPOC 2nd phase constructor
void CThreadEngine::ConstructL(CThreadAppView* aView)
	{
	CTimer::ConstructL();

	iView = aView;
	CActiveScheduler::Add( this );
	}

// ----------------------------------------------------------------------------
// CThreadEngine::StartL()
//
// Create threads and start Timer that resurrects threads. 
// ----------------------------------------------------------------------------
void CThreadEngine::StartL()
	{
	// Create threads only once
	if ( iCreatedThreads == EFalse )
		{
		CreateThreadsL();
		After( KThreadWatchdogInterval );
		}
	}

// ----------------------------------------------------------------------------
// CThreadEngine::RunL()
//
// Check that all threads are alive, if not then create and resume them again.
// After resuming, continue the thread animation.
// Called by the active scheduler when a request completion event occurs.
// ExitType can be used to check thread state ( killed / panicked / alive )
// ----------------------------------------------------------------------------
void CThreadEngine::RunL()
	{

	// Has thread one been killed?
	if ( iThreadOne.ExitType() == EExitKill ) 
		{
		HBufC* threadWasKilled = StringLoader::LoadLC( R_THREAD1_WAS_KILLED );
		iView->DrawText( *threadWasKilled );
		CleanupStack::PopAndDestroy( threadWasKilled );
		
		// Closing the handle finalises thread deconstructing. Thread with
		// same name can be opened aftewards. Without closing the handle new unique
		// name must be used. 
		iThreadOne.Close();

		// Create a new thread because earlier was killed
		if ( iThreadOne.Create( _L("thread1"), ExecuteThreadOne, 4096, KMinHeapSize, 
			 256*KMinHeapSize, &iNotSynchonizedCounter) != KErrNone )
			{
			// Create failed. This should not happen.
			HBufC* threadCreateFailureText = StringLoader::LoadLC( R_THREAD1_CREATE_FAILURE );
			iView->DrawText( *threadCreateFailureText );
			CleanupStack::PopAndDestroy( threadCreateFailureText);
			}
		else 
			{	
			// Start newly created thread
			iThreadOne.Resume();
			// Start the threadOne animation
			iView->iAnimationOne->StartAnimationL();
			}		
		}

	// Has thread two been killed?
	if ( iThreadTwo.ExitType() == EExitKill ) 
		{
		HBufC* threadWasKilled = StringLoader::LoadLC( R_THREAD2_WAS_KILLED );
		iView->DrawText( *threadWasKilled );
		CleanupStack::PopAndDestroy( threadWasKilled );

		iThreadTwo.Close();

		// Create a new thread because earlier was killed
		if ( KErrNone != iThreadTwo.Create( _L("thread2") , ExecuteThreadTwo, 4096, KMinHeapSize, 
			 256*KMinHeapSize, this ) )
			{
			// Create failed. This should not happen.
			HBufC* threadCreateFailureText = StringLoader::LoadLC( R_THREAD2_CREATE_FAILURE );
			iView->DrawText( *threadCreateFailureText );
			CleanupStack::PopAndDestroy( threadCreateFailureText);
			}
		else 
			{
			// Start newly created thread
			iThreadTwo.Resume();
			iView->iAnimationTwo->StartAnimationL();
			}
		}
		
	// Has thread three been killed?
	if ( iThreadThree.ExitType() == EExitKill ) 
		{
		HBufC* threadWasKilled = StringLoader::LoadLC( R_THREAD3_WAS_KILLED );
		iView->DrawText( *threadWasKilled );
		CleanupStack::PopAndDestroy( threadWasKilled );

		iThreadThree.Close();

		// Create a new thread because earlier was killed
		if ( KErrNone != iThreadThree.Create( _L("thread3") , ExecuteThreadThree, 4096, KMinHeapSize, 
			 256*KMinHeapSize, this) ) 
			{
			// Create failed. This should not happen.
			HBufC* threadCreateFailureText = StringLoader::LoadLC( R_THREAD1_CREATE_FAILURE );
			iView->DrawText( *threadCreateFailureText );
			CleanupStack::PopAndDestroy( threadCreateFailureText );
			}
		else 
			{
			// Start newly created thread
			iThreadThree.Resume();
			iView->iAnimationThree->StartAnimationL();
			}
		}
 
	// Wait for a while and run the same function again 
	After( KThreadWatchdogInterval );
	}

// ----------------------------------------------------------------------------
// CThreadEngine::DoCancel()
//
// Cancel and stop the timer. 
// ----------------------------------------------------------------------------
void CThreadEngine::DoCancel()
	{
	Cancel();
	}

// ----------------------------------------------------------------------------
// CThreadEngine::RunError(TInt)
//
// Cancel and stop the timer. 
// ----------------------------------------------------------------------------
TInt CThreadEngine::RunError(TInt)
	{
	return KErrNone;
	}

// ----------------------------------------------------------------------------
// CThreadEngine::ThreadKilledText(const TDesC& aText, TInt aCount)
//
// Print text and a number after thread has been killed. Count reflects 
// how long thread was running. TempValue is needed for TInt to TDesC 
// conversion
// ----------------------------------------------------------------------------
void CThreadEngine::ThreadKilledText(const TDesC& aText, TInt aCount)
	{
	TBuf<50> tempBuf;

	tempBuf.Append( aText );
	tempBuf.AppendNum( aCount );
	iView->DrawText( tempBuf );	
	}

// ----------------------------------------------------------------------------
// CThreadEngine::KillThread(TInt aThreadCount)
//
// Kill threadOne (1) / threadTwo (2) / threadThree (3)
// and draw text that a thread has been killed. Stops animation
// after killing. Resets counters.
// ----------------------------------------------------------------------------
void CThreadEngine::KillThread(TInt aThreadCount)
	{
	//Do not kill before threads have been created
	if ( iCreatedThreads == EFalse )
		{
		return;
		}

	HBufC* killedText;

	switch( aThreadCount )
		{
		case 1:
			// Thread can be killed because handle is connected to it.
			iThreadOne.Kill(KErrNone);

			killedText = StringLoader::LoadLC(R_KILLED_THREAD1);
			ThreadKilledText( *killedText, iNotSynchonizedCounter);
			CleanupStack::PopAndDestroy(killedText);

			iNotSynchonizedCounter = 0;

			iView->iAnimationOne->StopAnimation();
			
		break;
		case 2:
			iThreadTwo.Kill(KErrNone);

			killedText = StringLoader::LoadLC(R_KILLED_THREAD2);
			ThreadKilledText( *killedText, iSynchronizedCounter);
			CleanupStack::PopAndDestroy(killedText);

			// Reset counter
			SetSyncValue(0);
			
			iView->iAnimationTwo->StopAnimation();

		break;
		case 3:
			iThreadThree.Kill(KErrNone);

			killedText = StringLoader::LoadLC(R_KILLED_THREAD3);
			ThreadKilledText( *killedText, iSynchronizedCounter );
			CleanupStack::PopAndDestroy( killedText );

			// Reset counter
			SetSyncValue(0);
			
			iView->iAnimationThree->StopAnimation();
		break;
		}
	}

// ----------------------------------------------------------------------------
// CThreadEngine::ExecuteThread(TAny *aPtr)
//
// Threadfunction of threadOne. Executed only by threadOne.
// ----------------------------------------------------------------------------
TInt CThreadEngine::ExecuteThreadOne(TAny *aPtr)
	{
	// Convert pointer
	TInt* notSync = static_cast<TInt*>(aPtr);
	
	TBool loopConditionOne = ETrue;
	while ( loopConditionOne )
		{
		// iNotSynchonizedCounter++, synhronization is not needed because
		// only this thread changes iNotSynchronizedCount value.
		*notSync = *notSync + 1;
		// Wait for a while
		User::After( KThreadUpdateInterval );
		}

	return KErrNone;
	}

// ----------------------------------------------------------------------------
// CThreadEngine::ExecuteThreadTwo(TAny *aPtr)
//
// Threadfunction of threadTwo. Executed only by threadTwo.
// ----------------------------------------------------------------------------
TInt CThreadEngine::ExecuteThreadTwo(TAny *aPtr)
	{
	// Convert pointer
	CThreadEngine* engine = static_cast<CThreadEngine*>(aPtr);
	
	TBool loopConditionTwo = ETrue;
	while ( loopConditionTwo )
		{
		// iSynchronizedCounter++;
		// The counter is not handled directly, because two threads
		// interact with the same variable. Synchronization is needed.
		engine->SetSyncValue(engine->GetSyncValue()+1);
		User::After( KThreadUpdateInterval );
		}

	return KErrNone;
	}

// ----------------------------------------------------------------------------
// CThreadEngine::ExecuteThreadThree(TAny *aPtr)
//
// Threadfunction of threadThree. Executed only by threadThree.
// ----------------------------------------------------------------------------
TInt CThreadEngine::ExecuteThreadThree(TAny *aPtr)
	{
	CThreadEngine* engine = static_cast<CThreadEngine*>(aPtr);

	TBool loopConditionThree = ETrue;
	while ( loopConditionThree )
		{
		// iSynchronizedCounter++;
		// The counter is not handled directly, because two threads
		// interact with the same variable. Synchronization is needed.
		engine->SetSyncValue(engine->GetSyncValue()+1);
		User::After( KThreadUpdateInterval );
		}

	return KErrNone;
	}

// ----------------------------------------------------------------------------
// CThreadEngine::SetSyncValue(TInt aValue)
//
// Set the iSynchronizedCounter value. Synchronization is implemented by using
// a semaphore. Function is thread-safe.
// ----------------------------------------------------------------------------
void CThreadEngine::SetSyncValue(TInt aValue)
	{
	iMutex.Wait();
	iSynchronizedCounter = aValue;
	iMutex.Signal();
	}

// ----------------------------------------------------------------------------
// CThreadEngine::GetSyncValue() const
//
// Returns iSynchronizedCounter. 
// 
// ----------------------------------------------------------------------------
TInt CThreadEngine::GetSyncValue() const
	{
	return iSynchronizedCounter;
	}

// ----------------------------------------------------------------------------
// CThreadEngine::CreateThreadsL()
//
// Create three threads and resume them. Start thread animations.
// 
// ----------------------------------------------------------------------------
void CThreadEngine::CreateThreadsL()
	{
	//Create thread1
	iThreadOne.Create( _L("thread1") , ExecuteThreadOne, 4096, KMinHeapSize, 256*KMinHeapSize, 
		&iNotSynchonizedCounter);
	iThreadOne.Resume();
	iView->iAnimationOne->StartAnimationL();

	// Create thread2
	// thread two and three modify same counter, that is why a pointer to this class is given,
	// not the counter itself. Threads modify iSynchronizedCounter through two CThreadEngine 
	// functions: GetSyncValue() / SetSyncValue(). Thread2 gets a pointer to CThreadEngine,
	// because it must use synchronized funtions to increment the counter.
	iThreadTwo.Create( _L("thread2") , ExecuteThreadTwo, 4096, KMinHeapSize, 256*KMinHeapSize,
		this);	
	iThreadTwo.Resume();
	iView->iAnimationTwo->StartAnimationL();

	//Create thread3
	iThreadThree.Create(_L("thread3") , ExecuteThreadThree, 4096, KMinHeapSize, 256*KMinHeapSize,
		this );
	iThreadThree.Resume();
	iView->iAnimationThree->StartAnimationL();

	// All threads have been now created. Threads can be killed.
	iCreatedThreads = ETrue;	
	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -