Join Now
Quality Rating:
  • Currently 4.5 / 5
(4.5 / 5 - 2 votes cast)
Expertise Level:
  • Currently 4.5 / 5
(4.5 / 5 - 2 votes cast)

This page was last modified 11:04, 28 March 2008.

CS000867 - RThread

From Forum Nokia Wiki


ID CS000867 Creation date March 28, 2008
Platform S60 3rd Edition, FP1 Tested on devices Nokia N95
Category Symbian C++ Subcategory Code Examples


Keywords (APIs, classes, methods, functions): RThread, CTrapCleanup, CActiveScheduler, CPeriodic

Overview

This RThread example shows how to:

  • Create a simple CMyThread thread class that runs RThread
  • How to listen for thread execution
  • How add cleanup stack support for threads
  • How add active scheduler support for threads

The CMyThread thread runs the CPeriodic timer.


MMP file

RThread needs

LIBRARY euser.lib

Header

#include <e32base.h>
 
class MThreadExecuteObserver
    {
    public:
        virtual void ThreadExecuted(TInt aError) = 0;
    };
 
class CMyThread : public CActive, public MThreadExecuteObserver
    {
    public:
        static CMyThread* NewL(MThreadExecuteObserver& aObserver);
        virtual ~CMyThread();
        TInt ExecuteThread(TTimeIntervalMicroSeconds32 anInterval);
        inline TTimeIntervalMicroSeconds32 Interval(){return iInterval;};
 
    private: // From MThreadExecuteObserver
        void ThreadExecuted(TInt aError);
    
    private: // From CActive
        void RunL();
        void DoCancel();
    
    private:
        CMyThread(MThreadExecuteObserver& aObserver);
        void ConstructL();
        void CreateThreadL();
        TInt StartThread();
        static TInt ThreadFunction(TAny* aParams);
        static TInt PeriodicTick(TAny* aObject);
        
    private:
        MThreadExecuteObserver&         iObserver;
        RThread                         iThread;
        TTimeIntervalMicroSeconds32     iInterval;
    };

Source

#include "CMyThread.h"
 
const TInt KStackSize = 16384;
_LIT(KExecThreadBaseName, "CMyThread");
 
// Global thread id counter for making CMyThread thread names unique.
// This is achieved by appending counter to the end of thread name and
// incrementing counter value for next thread.
// This is writable static data.
TInt g_thread_id_counter = 0;
 
LOCAL_C void GenerateUniqueName(TDes& aResult, CMyThread* aExecutor)
    {
    _LIT(KHexFormat, "_0x%x");
    _LIT(KCounterFormat, "_%d");
    aResult.Copy(KExecThreadBaseName);
    aResult.AppendFormat(KHexFormat, aExecutor);
    g_thread_id_counter++;
    aResult.AppendFormat(KCounterFormat, g_thread_id_counter);
    }
 
CMyThread* CMyThread::NewL(MThreadExecuteObserver& aObserver)
    {
    CMyThread* self = new (ELeave) CMyThread(aObserver);
    CleanupStack::PushL(self);
    self->ConstructL();
    CleanupStack::Pop(self);
    return self;
    }
 
CMyThread::CMyThread(MThreadExecuteObserver& aObserver)
    : CActive(EPriorityStandard),iObserver(aObserver)
    {
    CActiveScheduler::Add(this);
    }
 
CMyThread::~CMyThread()
    {
    Cancel();
    iThread.Close();
    }
 
void CMyThread::ConstructL()
    {
    }
 
TInt CMyThread::ExecuteThread(TTimeIntervalMicroSeconds32 anInterval)
    {
    TInt ret = KErrNone;
    iInterval = anInterval;
    TRAP(ret,CreateThreadL());
    if (!ret)
        {
        ret = StartThread();
        }
    return ret;
    }
 
TInt CMyThread::StartThread()
    {
    TInt ret = KErrNone;
    if(!IsActive())
        {
        // Requests notification when this thread dies
        // normally or otherwise
        iThread.Logon(iStatus);
        SetActive();
        iThread.Resume();
        }
    else
        {
        ret = KErrOverflow;
        }
    return ret;
    }
 
void CMyThread::ThreadExecuted(TInt aError)
    {
    iObserver.ThreadExecuted(aError);
    }
 
void CMyThread::RunL()
    {
    iObserver.ThreadExecuted(iStatus.Int());
    }
 
void CMyThread::DoCancel()
    {
    iThread.LogonCancel(iStatus);
    iThread.Kill(KErrCancel);
    }
 
void CMyThread::CreateThreadL()
    {
    HBufC* threadName = HBufC::NewLC(KMaxFileName);
    TPtr ptr = threadName->Des();
    GenerateUniqueName(ptr, this);
 
    User::LeaveIfError(iThread.Create(
                        *threadName,
                        CMyThread::ThreadFunction,
                        KStackSize,
                        NULL,
                        this));
  
    CleanupStack::PopAndDestroy(threadName);
    }
 
TInt CMyThread::ThreadFunction(TAny* aParams)
    {
    // 1. Add cleanup stack support.
    CTrapCleanup* cleanupStack = CTrapCleanup::New();
 
    // 2. Get pointer to thread host
    CMyThread* host = (CMyThread*)aParams;
    
    TRAPD(err,
        // 3. Add support for active objects
        CActiveScheduler* activeScheduler = new (ELeave) CActiveScheduler;
        CleanupStack::PushL(activeScheduler);
        CActiveScheduler::Install(activeScheduler);
 
        // 4. Create and start CPeriodic class that is executed in this thread
        CPeriodic* periodic = CPeriodic::NewL(CActive::EPriorityLow);
        CleanupStack::PushL(periodic);
        periodic->Start(host->Interval(),host->Interval(),
        TCallBack(host->PeriodicTick, host));
 
        // NOTE: When adding CActiveScheduler support for threads we have to
        // add atleast one active object in it or it fails on 
        // CActiveScheduler::Start().
        // CPeriodic is derived from CActive active object so that is good for
        // this example.
        
        // 5. --> Thread execution starts
        CActiveScheduler::Start();
        // 6. --> Thread execution ends (waiting for CActiveScheduler::Stop())
 
        CleanupStack::PopAndDestroy(periodic);
        CleanupStack::PopAndDestroy(activeScheduler);
        );
 
    host->ThreadExecuted(err);
    delete cleanupStack;
    return KErrNone;
    }
 
TInt CMyThread::PeriodicTick(TAny* aObject)
    {
    CMyThread* mythread = (CMyThread*)aObject;
    if (mythread)
        {
        // Thread is executed once so time to stop it
        CActiveScheduler::Stop();
        // After this execution continues from CActiveScheduler::Start()
        }
    // Does not continue again 
    // Note: Does not work with this CPeriodic class
    return EFalse; 
    }

Running the CMyThread

Place CMyThread into class member variable and execute it

TTimeIntervalMicroSeconds32 time(100);
iMyThread = CMyThread::NewL(*this);
iMyThread->ExecuteThread(time);

When the thread is executed and it calls its observer that is a reference parameter in CMyThread::NewL(*this)

void CYourClass::ThreadExecuted(TInt aError)
    {
    // Will be called after thread execution
    }

Postconditions

The thread has been created and executed.

Related Discussions
Thread Thread Starter Forum Replies Last Post
How to include windows.h in Series60 vinhcyim General Symbian C++ 1 2006-06-29 05:26
TFindFile within RThread Mike24Productions General Symbian C++ 3 2006-02-26 20:41
how to adjust thread's priority kknd47 General Symbian C++ 4 2006-01-27 01:46
Multiplication Crashes on Device...? sym_coder General Symbian C++ 3 2006-03-28 09:23
Threads pmdr05 General Symbian C++ 2 2007-01-25 08:10
 
Powered by MediaWiki
     
     RDF Facets:
     
     
     qfnZtopicQUqfnTopicZseriesE5f60Q
     qfnZtypeQUqfnTypeZCommunityContentQ
     qfnZtypeQUqfnTypeZWebpageQ
     qfnZtypeQUqfnTypeZWikiContentQ
     qmarsZlanguageQUxhttpE3aE2fE2fswE2enokiaE2ecomE2flanguageE2d1E2fenX