This document illustrates how to use one active object to control another.
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:
issues a request to
the CExampleActiveObject active object
cancels any outstanding
request to the CExampleActiveObject active object
does nothing
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.

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 initializes 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() function 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()));
} The class CMessageKeyProcessor is
a concrete class, derived from CActiveConsole. It provides
an implementation for theProcessKeyPress() function and can
issue or cancel requests to aCExampleActiveObject 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 first constructor
parameter specifies a CConsoleBase which will be used to
provide asynchronous keyboard input.
the second constructor
parameter specifies a CExampleActiveObject which will be
controlled by this CMessageKeyProcessor.
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();
}
} In the code fragment below,
an active scheduler is created to which both a CMessageKeyProcessor active
object and aCExampleActiveObject 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
An instance of the active
scheduler, exampleScheduler is pushed onto the cleanup stack
and installed as the current active scheduler.
An instance of the CExampleActiveObject active
object is created.
An instance of the CMessageKeyProcessor active
object is created and this is in control.
keyProcessor->RequestCharacter() issues
a request for keyboard input.
CActiveScheduler::Start() starts
the active scheduler. At least one outstanding request is necessary before
the wait loop is started, otherwise the thread hangs. All further request
issuing and servicing occurs within this function. The wait loop continues
until one of the active objects’ RunL() callsCActiveScheduler::Stop().
The active objects and the active scheduler are popped from the cleanup stack and destroyed.