Symbian OS
read last symbian news on www.newlc.com read last symbian reviews on www.newlc.com
read last symbian tutorial on www.newlc.com read last symbian download on www.newlc.com
19 juin 2007 - 12:27
Keywords :

As we know, active object is widely used in Symbian C++ to take care of running multitask in the same thread. Here I will not explain much about the Active Object mechanism, because there're tons of ariticles about this. Just google it and you will get them. Here I would like to talk about something interesting.

Normally, we use active object like this everyday.

class MyAO : public CActive
{
RXX iAOObj;
}

void MyAO::AsynchronousFun()
{
        iAOObj.IssueAsynOpr( iStatus );
        SetActive();
}

void MyAO::RunL()
{
        // called after IssueAsynOpr finishes
}

Here, class RXX is usually a client side handle of a server side object which runs in another process(the service provider). Through the handle, the client does IPC(Inter Process Communication) with the server. Since the server runs in some other process, so the operation won't block client's thread.

When the operation in the server side completes, it will compelete client's message so that client thread's Active Schedular knows the operation finishes and then client's RunL() get called.

In many cases, you need to implement your own service provider, say, you have to implement IssueAsynOpr() function of class RXX or you have to create a new thread to handle the asynchronous operation. Here's a common example on how to deal with Active Object and thread.

Fun()
{
        AsynOp( iStatus );
        SetActive();
}

AsynOp( TRequestStatus& aStatus )
{
        aStatus = KRequestPending;        // must have this line !
        RThread thread;
        thread.Create( ... aStatus );        // pseudocode here
}

RunL()                // get called after AsynOp() finishes
{}

What's interesting is that you have to give aStatus a value "KRequestPending" explicitly here. In Symbian 9 onwards, if you don't do that in AsynOp(), after SetActive() is invoked and before Fun() returns, application will panic. The panic code is E32User-CBase 46. If you take a look at the SDK helper the reason is "This panic is raised by an active scheduler, a CActiveScheduler. It is caused by a stray signal.".

But in Symbian pre 9, if you call SetActive() without doing "aStatus = KRequestPending;", some time later RunL() will get called. But when you try to call SetActive() again, RunL() won't be called this time, call SetActive() again, application crashes without any error message!

Though it can be considered it's a kind of programming fault, the behaviour in Symbian pre 9 still can't be accpeted, because there's no error message. Obviously, in Symbian 9 onwards, it has been improved. Then how does active scheduler/active object identify the problem?

If you look into the declaration of class TRequestStatus(e32cmn.h) in Symbian 9 onwards, you will find an interesting enum which doesn't exist in Symbian pre 9:

enum
{
        EActive                        = 1,  //bit0
        ERequestPending                = 2,  //bit1
};

Let's talk about this later. You will also know that the overloaded '=' operator is inlined, so you can find the source code of this function in e32cmn.inl. Take a look at it, the code is:

inline TInt TRequestStatus::operator=(TInt aVal)
{
        if(aVal==KRequestPending)
                iFlags|=TRequestStatus::ERequestPending;
        else
                iFlags&=~TRequestStatus::ERequestPending;
        return (iStatus=aVal);
}

According to the logic, you can see operator=() will check if aVal is KRequestPending(the one we used in "aStatus = KRequestPending;" remember?). If it is, then do iFlag |= 0010, and after that it will finally set the iStatus to aVal. Meaning that when we do "aStatus = KRequestPending;" system will actually do two things, set iFlags and set iStatus(only do the second one in Symbian pre 9).

After we call SetActive(), what is going to happen? If you take a look at the class declaration of CActive class, you will find it's interesting that in Symbian pre 9, there's a TBool variable named "iActive" to indicate if an active object is active. In Symbian 9 onwards, this variable is eliminated! You may wonder how do active object know it's active. I guess that's the reason why "EActive" is added in TRequestStatus class. In SetActive() I guess it will do:

iFlags|=TRequestStatus::EActive;

After that, iFlag will become 0011 from 0010. And at the same time the value of iStatus is KRequestPending. What is this suppose to mean. It means that active schedular can know if the active object's iStatus is KRequestPending and if the active object is active by checking the single variable, which is "iFlags"(check the bits)! Right? That's why CActive has confidence to eliminate the iActive memeber.

Or we can say, now active schedular has the ability to tell if an active object calls SetActive() without issuing any outstanding operation. If not, then panic with E32Base-46 error. This is reasonable, because this will help developers to identify the programming fault.

Since I can't see the source code of Active Object/Active Schedular, sometimes I have to guess the behavour of them. If I made some mistakes, please kindly to tell me, thank you.

You can also find this ariticle in my blog : www.SymbianSIG.com

Tutorial posted juin 19th, 2007 by rensijie

copyright 2003-2009 NewLC SARL