Symbian
Symbian Developer Library

SYMBIAN OS V9.4

Feedback

[Index] [Previous] [Next]


How to use multiple active objects

The following example code fragments show how to construct a program with two active objects, where one controls the initiation and cancellation of the other.

In these examples:

CActiveConsole is an active object and contains a pointer to a CConsoleBase object which is a service provider. Through this service provider, the active object provides the facility to request a character from the keyboard.

RunL() delegates the handling of completed requests to the pure virtual function ProcessKeyPress(), which must be provided by a derived class.

CMessageKeyProcessor is further derived from CActiveConsole and contains a pointer to another active object CExampleActiveObject, which requires input from the keyboard.

Depending on the input character, the CMessageKeyProcessor active object does one of the following:

The implementation of the CExampleActiveObject active object is not relevant to the example and is not shown.

The following diagram shows the relationship between the classes.


[Top]


Encapsulating the service provider

The class CActiveConsole encapsulates the provision of basic keyboard services. Its iConsole data member is a pointer to the service provider, the CConsoleBase object.

The active object class is defined as:

class CActiveConsole : public CActive
    {
public:
    CActiveConsole(CConsoleBase* aConsole);
    void ConstructL();
    ~CActiveConsole();
    void RequestCharacter();
    void RunL();
    void DoCancel();
    virtual void ProcessKeyPress(TChar aChar)=0;
protected:
    CConsoleBase* iConsole; 
    };

The class constructor takes a pointer to a CConsoleBase object as its single argument and initialises its iConsole data member to this value:

CActiveConsole::CActiveConsole(CConsoleBase* aConsole)
    : iConsole(aConsole)
    {}

The ConstructL() function adds the active object to the active scheduler:

void CActiveConsole::ConstructL()
    {
    CActiveScheduler::Add(this);
    }

The destructor cancels any outstanding request before destroying the active object:

CActiveConsole::~CActiveConsole()
    {
    Cancel();
    }

DoCancel() is implemented to cancel the request to iConsole.

The RequestCharacter() function makes a request for a key press to the service provider by calling iConsole->Read(iStatus) and setting the active request flag:

void CActiveConsole::RequestCharacter()
    {
    iConsole->Read(iStatus);
    SetActive();
    }

The RunL() funcion makes a call to the ProcessKeyPress() function. This is a pure virtual function that derived classes must implement to handle the key press and to reissue the request:

void CActiveConsole::RunL()
    {
    ProcessKeyPress(TChar(iConsole->KeyCode()));
    }

[Top]


Further deriving from the active object

The class CMessageKeyProcessor is a concrete class, derived from CActiveConsole. It provides an implementation for the ProcessKeyPress() function and can issue or cancel requests to a CExampleActiveObject active object.

This active object class is defined as:

class CMessageKeyProcessor : public CActiveConsole
    {
public:
    ...
    CMessageKeyProcessor(CConsoleBase* aConsole, CExampleActiveObject* iExampleObject);
    void ProcessKeyPress(TChar aChar);
private:
    CExampleActiveObject* iExampleObject;
    };

Notes

The behaviour of the ProcessKeyPress() function depends on the key code value:

void CMessageKeyProcessor::ProcessKeyPress(TChar aChar)
    {
    if (aChar == 'm' || aChar == 'M')
        {
        iExampleObject->Cancel();
        iExampleObject->IssueRequest();
        }
    if (aChar == 'c' || aChar == 'C')
        {
        iExampleObject->Cancel();
        }
    if (aChar != EKeyEscape)
        {
        RequestCharacter();
        }
    else
        {
        iExampleObject->Cancel();
        CActiveScheduler::Stop();
        }
    }

[Top]


Enhanced framework

In the code fragment below, an active scheduler is created to which both a CMessageKeyProcessor active object and a CExampleActiveObject active object are added:

LOCAL_C void doExampleL()
    {
    CActiveScheduler* exampleScheduler=new (ELeave) CActiveScheduler;
    CleanupStack::PushL(exampleScheduler);
    CActiveScheduler::Install(exampleScheduler);

    CExampleActiveObject* iExampleObject =
            CExampleActiveObject::NewLC();
    CMessageKeyProcessor* keyProcessor=
             CMessageKeyProcessor::NewLC(console, iExampleObject);

    keyProcessor->RequestCharacter();
    CActiveScheduler::Start();
    CleanupStack::PopAndDestroy(3);
    }

Notes