How to construct an active object

This document describes how to construct an active object to encapsulate a service provider.

The following examples outline the practical framework required when implementing an active object

Active objects framework

The following example code demonstrates how to construct the framework for a simple active object which encapsulates a service-provider.

First define and implement the service-provider class. The following code shows the typical features:

class CExampleServiceProvider
    {
public:
    ...
    void RequestTheService(TRequestStatus& aStatus);
    void CancelTheRequest();
private:
    TInt iResult ;
    };

Now define and implement the active object which wraps around the service provider. The following code shows the main features of an active object class.

  • Provide a constructor.

  • Provide a RunL() function to handle the completion of an asynchronous request.

  • Provide a DoCancel() function to implement a cancellation request.

  • Provide a RunError() function to implement recovery and cleanup if the RunL() function leaves. Note that this is not available in v5.

class CExampleActiveObject : public CActive;
    {
public:
    CExampleActiveObject(CExampleServiceProvider* aServiceProvider);
    ~CExampleActiveObject;
    void IssueRequest();
private:
    void DoCancel();
    void RunL();
    TInt RunError(TInt aError);
private:
    CExampleServiceProvider* iServiceProvider ;
    };

When the class codes a DoCancel() then the destructor must call the Cancel() member function of the active object.

How to construct an active object

The following code shows the typical elements required when constructing an active object.

CExampleActiveObject::CExampleActiveObject(CExampleServiceProvider* aServiceProvider) : CActive(EPriorityStandard)
    {
    iServiceProvider = aServiceProvider; // Store pointer to service provider
    CActiveScheduler::Add(this) ;        // add to active scheduler
    }
  • Set the active object’s priority using one of the CActive::Tpriority enumeration values.

  • Retain a handle to the required service provider, so that request functions can pass on a request to the asynchronous service provider.

  • Use add() to add the active object to the active scheduler, in order to ensure that its requests are handled.

In practice there are many variations on this basic construction theme.

  • Most active objects set the priority within the constructor and this is almost always the EPriorityStandard or zero value. In some cases, the choice of priority value is decided by the caller or by the constructor of a class further derived from this one.

  • In many situations, the service provider is constructed by the active object itself, instead of being passed in. Often this is done as part of a two stage construction process. For example, the CTimer active object has a simple constructor and a function ConstructL() which completes the construction of the object:

CTimer::CTimer(TInt aPriority)
    : CActive(aPriority)
    {
    }
void CTimer::ConstructL()
    {
    TInt r=iTimer.CreateLocal();
    if (r!=KErrNone)
        {
        User::Leave(r);
        }
    }