A simple 'hello world' style active object.
The example active object encapsulates an RTimer
and calls the asynchronous function RTimer::After()
.
CActive
. class CMyTimer : public CActive { public: // Factory functions to instantiate the class. static CMyTimer* NewLC(); static CMyTimer* NewL(); // Destructor. ~CMyTimer(); // Inherited pure virtual functions. void DoCancel(); void RunL(); // Error handling. TInt RunError( TInt aError ); // The function that makes the asynchronous request. void MakeRequest( TUint aDelay ); protected: // First and second phase constructors, called by // the factory functions NewL() and NewLC() CMyTimer(); void ConstructL(); private: // The object used to make the asynchronous request. // This is often called the 'asynchronous service provider'. RTimer iTimer; };Here is some sample code to instantiate the active object and make an asynchronous request:
// Create an active scheduler for the thread. // An active scheduler is needed to manage one or more active // objects. CActiveScheduler* scheduler = new (ELeave) CActiveScheduler; // Use the cleanup stack to ensure the active scheduler // is deleted in the event of a leave. CleanupStack::PushL( scheduler ); // Install the active scheduler for the current thread. CActiveScheduler::Install( scheduler ); // Instantiate the active object. CMyTimer* timer = CMyTimer::NewLC(); // Make an asynchronous request. timer->MakeRequest( 2000000 ); // Start the active scheduler's loop. CActiveScheduler::Start(); // Clean up. CleanupStack::PopAndDestroy( 2, scheduler );
Note. The Qt and AVKON application frameworks create, install, and start the active scheduler for the main application thread. The code above is for tutorial purposes only.
MakeRequest()
:void CMyTimer::MakeRequest(TUint aDelay) { // Cancel a previous request. A single active // object can only have one request outstanding // at once. Cancel(); // Pass in the active object's TRequestStatus // member iStatus when making the request. iTimer.After( iStatus, aDelay ); // Inform the active scheduler that the active // object has an outstanding asynchronous request. SetActive(); }When the request completes the active scheduler will call the active object's
RunL()
method. RunL()
is a pure virtual method that you must override. Use this method
to define the behaviour required as a result of request completion.void CMyTimer::RunL() { // Take appropriate action as a result of the // completion of the request. You could make another // request, using this or another active object. }
Cancelling a request
DoCancel()
method of the base class to terminate a request by calling the appropriate
cancellation method on the asynchronous service provider.CMyTimer::~CMyTimer() { // Invoke the base class Cancel(). This calls // our DoCancel() override if a request is // outstanding. Cancel(); // Clean up RTimer. iTimer.Close(); } void CMyTimer::DoCancel() { // Call cancellation function of the asynchronous // service provider. iTimer.Cancel(); }
Error handling
RunL()
callback method of an active object
leaves, the framework invokes the virtual RunError()
method of the active object. If you are able to handle the error,
return KErrNone
from RunError()
. // Called by the active scheduler if RunL() leaves. // The parameter aError contains the leave code. TInt CMyTimer::RunError( TInt aError ) { // Take action to handle the error ... // Indicate that the error has been handled. return KErrNone; }
If you choose not to handle the leave inside RunError()
the framework calls CActiveScheduler::Error()
.
The default implementation of this virtual method is to panic the
thread (EUSER-CBase 47
).
Member functions to create the active object
// Factory function. CMyTimer* CMyTimer::NewL() { CMyTimer* self = NewLC(); CleanupStack::Pop( self ); return self; } // Factory function that returns the address // of the object on the cleanup stack. CMyTimer* CMyTimer::NewLC() { CMyTimer* self = new (ELeave) CMyTimer(); CleanupStack::PushL( self ); self->ConstructL(); return self; } // Constructor sets the priority of the // active object. The active scheduler stores the // active objects in a priority ordered list. CMyTimer::CMyTimer() : CActive( CActive::EPriorityStandard ) {} // Second phase constructor. void CMyTimer::ConstructL() { // Initialize the asynchronous service provider. User::LeaveIfError( iTimer.CreateLocal() ); // Add the active object to the active // scheduler's list. CActiveScheduler::Add( this ); }