picodrive/platform/uiq3/engine/polledas.cpp
notaz cc68a136aa initial import
git-svn-id: file:///home/notaz/opt/svn/PicoDrive@2 be3aeb3a-fb24-0410-a615-afba39da0efa
2006-12-19 20:53:21 +00:00

269 lines
7.5 KiB
C++

/*******************************************************************
*
* File: PolledAS.cpp
*
* Author: Peter van Sebille (peter@yipton.net)
*
* (c) Copyright 2002, Peter van Sebille
* All Rights Reserved
*
*******************************************************************/
/*
* Oh Lord, forgive me for I have sinned.
* In their infinite wisdom, Symbian Engineers have decided that
* the Active Scheduler's queue of Active Objects is private
* and no getters are provided... sigh.
* This mere mortal will have to excercise the power of C pre-processor
* once more to circumvent the will of the gods.
*/
#include <e32std.h>
// from e32base.h
class CBase
{
public:
/**
Default constructor
*/
inline CBase() {}
IMPORT_C virtual ~CBase();
inline TAny* operator new(TUint aSize, TAny* aBase) __NO_THROW { Mem::FillZ(aBase, aSize); return aBase; }
inline TAny* operator new(TUint aSize) __NO_THROW { return User::AllocZ(aSize); }
inline TAny* operator new(TUint aSize, TLeave) { return User::AllocZL(aSize); }
inline TAny* operator new(TUint aSize, TUint aExtraSize) { return User::AllocZ(aSize + aExtraSize); }
inline TAny* operator new(TUint aSize, TLeave, TUint aExtraSize) { return User::AllocZL(aSize + aExtraSize); }
IMPORT_C static void Delete(CBase* aPtr);
protected:
IMPORT_C virtual TInt Extension_(TUint aExtensionId, TAny*& a0, TAny* a1);
private:
CBase(const CBase&);
CBase& operator=(const CBase&);
private:
};
class TRequestStatusFaked
{
public:
inline TRequestStatusFaked() : iFlags(0) {};
inline TRequestStatusFaked(TInt aVal) : iStatus(aVal), iFlags(aVal==KRequestPending ? TRequestStatusFaked::ERequestPending : 0) {}
/* inline TInt operator=(TInt aVal);
inline TBool operator==(TInt aVal) const;
*/
inline TBool operator!=(TInt aVal) const {return(iStatus!=aVal);}
/*
inline TBool operator>=(TInt aVal) const;
inline TBool operator<=(TInt aVal) const;
inline TBool operator>(TInt aVal) const;
inline TBool operator<(TInt aVal) const;
inline TInt Int() const;
private:
*/
enum
{
EActive = 1, //bit0
ERequestPending = 2, //bit1
};
TInt iStatus;
TUint iFlags;
friend class CActive;
friend class CActiveScheduler;
friend class CServer2;
};
class CActive : public CBase
{
public:
enum TPriority
{
EPriorityIdle=-100,
EPriorityLow=-20,
EPriorityStandard=0,
EPriorityUserInput=10,
EPriorityHigh=20,
};
public:
IMPORT_C ~CActive();
IMPORT_C void Cancel();
IMPORT_C void Deque();
IMPORT_C void SetPriority(TInt aPriority);
inline TBool IsActive() const {return(iStatus.iFlags&TRequestStatus::EActive);}
inline TBool IsAdded() const {return(iLink.iNext!=NULL);}
inline TInt Priority() const {return iLink.iPriority;}
protected:
IMPORT_C CActive(TInt aPriority);
IMPORT_C void SetActive();
virtual void DoCancel() =0;
virtual void RunL() =0;
IMPORT_C virtual TInt RunError(TInt aError);
protected:
IMPORT_C virtual TInt Extension_(TUint aExtensionId, TAny*& a0, TAny* a1);
public:
TRequestStatusFaked iStatus; // hope this will work
private:
// TBool iActive;
TPriQueLink iLink;
TAny* iSpare;
friend class CActiveScheduler;
friend class CServer;
friend class CServer2;
friend class CPrivatePolledActiveScheduler; // added
};
class CActiveScheduler : public CBase
{
friend class CActiveSchedulerWait;
public:
struct TLoop;
typedef TLoop* TLoopOwner;
public:
IMPORT_C CActiveScheduler();
IMPORT_C ~CActiveScheduler();
IMPORT_C static void Install(CActiveScheduler* aScheduler);
IMPORT_C static CActiveScheduler* Current();
IMPORT_C static void Add(CActive* aActive);
IMPORT_C static void Start();
IMPORT_C static void Stop();
IMPORT_C static TBool RunIfReady(TInt& aError, TInt aMinimumPriority);
IMPORT_C static CActiveScheduler* Replace(CActiveScheduler* aNewActiveScheduler);
IMPORT_C virtual void WaitForAnyRequest();
IMPORT_C virtual void Error(TInt aError) const;
IMPORT_C void Halt(TInt aExitCode) const;
IMPORT_C TInt StackDepth() const;
private:
static void Start(TLoopOwner* aOwner);
IMPORT_C virtual void OnStarting();
IMPORT_C virtual void OnStopping();
IMPORT_C virtual void Reserved_1();
IMPORT_C virtual void Reserved_2();
void Run(TLoopOwner* const volatile& aLoop);
void DoRunL(TLoopOwner* const volatile& aLoop, CActive* volatile & aCurrentObj);
friend class CPrivatePolledActiveScheduler; // added
protected:
IMPORT_C virtual TInt Extension_(TUint aExtensionId, TAny*& a0, TAny* a1);
protected:
inline TInt Level() const {return StackDepth();} // deprecated
private:
TLoop* iStack;
TPriQue<CActive> iActiveQ;
TAny* iSpare;
};
class TCleanupItem;
class CleanupStack
{
public:
IMPORT_C static void PushL(TAny* aPtr);
IMPORT_C static void PushL(CBase* aPtr);
IMPORT_C static void PushL(TCleanupItem anItem);
IMPORT_C static void Pop();
IMPORT_C static void Pop(TInt aCount);
IMPORT_C static void PopAndDestroy();
IMPORT_C static void PopAndDestroy(TInt aCount);
IMPORT_C static void Check(TAny* aExpectedItem);
inline static void Pop(TAny* aExpectedItem);
inline static void Pop(TInt aCount, TAny* aLastExpectedItem);
inline static void PopAndDestroy(TAny* aExpectedItem);
inline static void PopAndDestroy(TInt aCount, TAny* aLastExpectedItem);
};
/*
* This will declare CPrivatePolledActiveScheduler as a friend
* of all classes that define a friend. CPrivatePolledActiveScheduler needs to
* be a friend of CActive
*/
//#define friend friend class CPrivatePolledActiveScheduler; friend
/*
* This will change the:
* void DoStart();
* method in CActiveScheduler to:
* void DoStart(); friend class CPrivatePolledActiveScheduler;
* We need this to access the private datamembers in CActiveScheduler.
*/
//#define DoStart() DoStart(); friend class CPrivatePolledActiveScheduler;
//#include <e32base.h>
#include "PolledAS.h"
class CPrivatePolledActiveScheduler : public CActiveScheduler
{
public:
void Schedule();
};
void CPrivatePolledActiveScheduler::Schedule()
{
TDblQueIter<CActive> q(iActiveQ);
q.SetToFirst();
FOREVER
{
CActive *pR=q++;
if (pR)
{
//TRequestStatus::EActive = 1, //bit0
//TRequestStatus::ERequestPending = 2, //bit1
if (pR->IsActive() && pR->iStatus!=KRequestPending)
{
// pR->iActive=EFalse; // won't this cause trouble?
pR->iStatus.iFlags&=~TRequestStatusFaked::EActive;
//debugPrintFile(_L("as: %08x"), pR);
TRAPD(r,pR->RunL());
//pR->iStatus=TRequestStatus::ERequestPending;
break;
}
}
else
break;
}
}
static CPolledActiveScheduler* sPolledActiveScheduler = NULL;
CPolledActiveScheduler::~CPolledActiveScheduler()
{
sPolledActiveScheduler = NULL;
delete iPrivatePolledActiveScheduler;
}
CPolledActiveScheduler* CPolledActiveScheduler::NewL()
{
// if (sPolledActiveScheduler == NULL)
{
sPolledActiveScheduler = new(ELeave)CPolledActiveScheduler;
CleanupStack::PushL(sPolledActiveScheduler);
sPolledActiveScheduler->ConstructL();
CleanupStack::Pop();
}
return sPolledActiveScheduler;
}
void CPolledActiveScheduler::ConstructL()
{
iPrivatePolledActiveScheduler = new(ELeave) CPrivatePolledActiveScheduler;
iPrivatePolledActiveScheduler->Install(iPrivatePolledActiveScheduler);
}
void CPolledActiveScheduler::Schedule()
{
iPrivatePolledActiveScheduler->Schedule();
}
CPolledActiveScheduler* CPolledActiveScheduler::Instance()
{
// return (CPolledActiveScheduler*) CActiveScheduler::Current();
return sPolledActiveScheduler;
}