| 1 | /*******************************************************************\r |
| 2 | *\r |
| 3 | * File: PolledAS.cpp\r |
| 4 | *\r |
| 5 | * Author: Peter van Sebille (peter@yipton.net)\r |
| 6 | *\r |
| 7 | * (c) Copyright 2002, Peter van Sebille\r |
| 8 | * All Rights Reserved\r |
| 9 | *\r |
| 10 | *******************************************************************/\r |
| 11 | \r |
| 12 | /*\r |
| 13 | * Oh Lord, forgive me for I have sinned.\r |
| 14 | * In their infinite wisdom, Symbian Engineers have decided that\r |
| 15 | * the Active Scheduler's queue of Active Objects is private\r |
| 16 | * and no getters are provided... sigh.\r |
| 17 | * This mere mortal will have to excercise the power of C pre-processor \r |
| 18 | * once more to circumvent the will of the gods.\r |
| 19 | */\r |
| 20 | \r |
| 21 | \r |
| 22 | #include <e32std.h>\r |
| 23 | \r |
| 24 | // from e32base.h\r |
| 25 | class CBase\r |
| 26 | {\r |
| 27 | public:\r |
| 28 | /**\r |
| 29 | Default constructor\r |
| 30 | */\r |
| 31 | inline CBase() {}\r |
| 32 | IMPORT_C virtual ~CBase();\r |
| 33 | inline TAny* operator new(TUint aSize, TAny* aBase) __NO_THROW { Mem::FillZ(aBase, aSize); return aBase; }\r |
| 34 | inline TAny* operator new(TUint aSize) __NO_THROW { return User::AllocZ(aSize); }\r |
| 35 | inline TAny* operator new(TUint aSize, TLeave) { return User::AllocZL(aSize); }\r |
| 36 | inline TAny* operator new(TUint aSize, TUint aExtraSize) { return User::AllocZ(aSize + aExtraSize); }\r |
| 37 | inline TAny* operator new(TUint aSize, TLeave, TUint aExtraSize) { return User::AllocZL(aSize + aExtraSize); }\r |
| 38 | IMPORT_C static void Delete(CBase* aPtr);\r |
| 39 | protected:\r |
| 40 | IMPORT_C virtual TInt Extension_(TUint aExtensionId, TAny*& a0, TAny* a1);\r |
| 41 | private:\r |
| 42 | CBase(const CBase&);\r |
| 43 | CBase& operator=(const CBase&);\r |
| 44 | private:\r |
| 45 | };\r |
| 46 | \r |
| 47 | \r |
| 48 | class TRequestStatusFaked\r |
| 49 | {\r |
| 50 | public:\r |
| 51 | inline TRequestStatusFaked() : iFlags(0) {};\r |
| 52 | inline TRequestStatusFaked(TInt aVal) : iStatus(aVal), iFlags(aVal==KRequestPending ? TRequestStatusFaked::ERequestPending : 0) {}\r |
| 53 | /* inline TInt operator=(TInt aVal);\r |
| 54 | inline TBool operator==(TInt aVal) const;\r |
| 55 | */\r |
| 56 | inline TBool operator!=(TInt aVal) const {return(iStatus!=aVal);}\r |
| 57 | /*\r |
| 58 | inline TBool operator>=(TInt aVal) const;\r |
| 59 | inline TBool operator<=(TInt aVal) const;\r |
| 60 | inline TBool operator>(TInt aVal) const;\r |
| 61 | inline TBool operator<(TInt aVal) const;\r |
| 62 | inline TInt Int() const;\r |
| 63 | private:\r |
| 64 | */\r |
| 65 | enum\r |
| 66 | {\r |
| 67 | EActive = 1, //bit0\r |
| 68 | ERequestPending = 2, //bit1\r |
| 69 | };\r |
| 70 | TInt iStatus;\r |
| 71 | TUint iFlags;\r |
| 72 | friend class CActive;\r |
| 73 | friend class CActiveScheduler;\r |
| 74 | friend class CServer2;\r |
| 75 | };\r |
| 76 | \r |
| 77 | \r |
| 78 | class CActive : public CBase\r |
| 79 | {\r |
| 80 | public:\r |
| 81 | enum TPriority\r |
| 82 | {\r |
| 83 | EPriorityIdle=-100,\r |
| 84 | EPriorityLow=-20,\r |
| 85 | EPriorityStandard=0,\r |
| 86 | EPriorityUserInput=10,\r |
| 87 | EPriorityHigh=20,\r |
| 88 | };\r |
| 89 | public:\r |
| 90 | IMPORT_C ~CActive();\r |
| 91 | IMPORT_C void Cancel();\r |
| 92 | IMPORT_C void Deque();\r |
| 93 | IMPORT_C void SetPriority(TInt aPriority);\r |
| 94 | inline TBool IsActive() const {return(iStatus.iFlags&TRequestStatus::EActive);}\r |
| 95 | inline TBool IsAdded() const {return(iLink.iNext!=NULL);}\r |
| 96 | inline TInt Priority() const {return iLink.iPriority;}\r |
| 97 | protected:\r |
| 98 | IMPORT_C CActive(TInt aPriority);\r |
| 99 | IMPORT_C void SetActive();\r |
| 100 | virtual void DoCancel() =0;\r |
| 101 | virtual void RunL() =0;\r |
| 102 | IMPORT_C virtual TInt RunError(TInt aError);\r |
| 103 | protected:\r |
| 104 | IMPORT_C virtual TInt Extension_(TUint aExtensionId, TAny*& a0, TAny* a1);\r |
| 105 | public:\r |
| 106 | TRequestStatusFaked iStatus; // hope this will work\r |
| 107 | private:\r |
| 108 | // TBool iActive;\r |
| 109 | TPriQueLink iLink;\r |
| 110 | TAny* iSpare;\r |
| 111 | friend class CActiveScheduler;\r |
| 112 | friend class CServer;\r |
| 113 | friend class CServer2;\r |
| 114 | friend class CPrivatePolledActiveScheduler; // added\r |
| 115 | };\r |
| 116 | \r |
| 117 | \r |
| 118 | \r |
| 119 | class CActiveScheduler : public CBase\r |
| 120 | {\r |
| 121 | friend class CActiveSchedulerWait;\r |
| 122 | public:\r |
| 123 | struct TLoop;\r |
| 124 | typedef TLoop* TLoopOwner;\r |
| 125 | public:\r |
| 126 | IMPORT_C CActiveScheduler();\r |
| 127 | IMPORT_C ~CActiveScheduler();\r |
| 128 | IMPORT_C static void Install(CActiveScheduler* aScheduler);\r |
| 129 | IMPORT_C static CActiveScheduler* Current();\r |
| 130 | IMPORT_C static void Add(CActive* aActive);\r |
| 131 | IMPORT_C static void Start();\r |
| 132 | IMPORT_C static void Stop();\r |
| 133 | IMPORT_C static TBool RunIfReady(TInt& aError, TInt aMinimumPriority);\r |
| 134 | IMPORT_C static CActiveScheduler* Replace(CActiveScheduler* aNewActiveScheduler);\r |
| 135 | IMPORT_C virtual void WaitForAnyRequest();\r |
| 136 | IMPORT_C virtual void Error(TInt aError) const;\r |
| 137 | IMPORT_C void Halt(TInt aExitCode) const;\r |
| 138 | IMPORT_C TInt StackDepth() const;\r |
| 139 | private:\r |
| 140 | static void Start(TLoopOwner* aOwner);\r |
| 141 | IMPORT_C virtual void OnStarting();\r |
| 142 | IMPORT_C virtual void OnStopping();\r |
| 143 | IMPORT_C virtual void Reserved_1();\r |
| 144 | IMPORT_C virtual void Reserved_2();\r |
| 145 | void Run(TLoopOwner* const volatile& aLoop);\r |
| 146 | void DoRunL(TLoopOwner* const volatile& aLoop, CActive* volatile & aCurrentObj);\r |
| 147 | friend class CPrivatePolledActiveScheduler; // added\r |
| 148 | protected:\r |
| 149 | IMPORT_C virtual TInt Extension_(TUint aExtensionId, TAny*& a0, TAny* a1);\r |
| 150 | protected:\r |
| 151 | inline TInt Level() const {return StackDepth();} // deprecated\r |
| 152 | private:\r |
| 153 | TLoop* iStack;\r |
| 154 | TPriQue<CActive> iActiveQ;\r |
| 155 | TAny* iSpare;\r |
| 156 | };\r |
| 157 | \r |
| 158 | \r |
| 159 | \r |
| 160 | class TCleanupItem;\r |
| 161 | class CleanupStack\r |
| 162 | {\r |
| 163 | public:\r |
| 164 | IMPORT_C static void PushL(TAny* aPtr);\r |
| 165 | IMPORT_C static void PushL(CBase* aPtr);\r |
| 166 | IMPORT_C static void PushL(TCleanupItem anItem);\r |
| 167 | IMPORT_C static void Pop();\r |
| 168 | IMPORT_C static void Pop(TInt aCount);\r |
| 169 | IMPORT_C static void PopAndDestroy();\r |
| 170 | IMPORT_C static void PopAndDestroy(TInt aCount);\r |
| 171 | IMPORT_C static void Check(TAny* aExpectedItem);\r |
| 172 | inline static void Pop(TAny* aExpectedItem);\r |
| 173 | inline static void Pop(TInt aCount, TAny* aLastExpectedItem);\r |
| 174 | inline static void PopAndDestroy(TAny* aExpectedItem);\r |
| 175 | inline static void PopAndDestroy(TInt aCount, TAny* aLastExpectedItem);\r |
| 176 | };\r |
| 177 | \r |
| 178 | \r |
| 179 | /*\r |
| 180 | * This will declare CPrivatePolledActiveScheduler as a friend\r |
| 181 | * of all classes that define a friend. CPrivatePolledActiveScheduler needs to\r |
| 182 | * be a friend of CActive\r |
| 183 | */\r |
| 184 | //#define friend friend class CPrivatePolledActiveScheduler; friend\r |
| 185 | \r |
| 186 | \r |
| 187 | /*\r |
| 188 | * This will change the:\r |
| 189 | * void DoStart();\r |
| 190 | * method in CActiveScheduler to:\r |
| 191 | * void DoStart(); friend class CPrivatePolledActiveScheduler;\r |
| 192 | * We need this to access the private datamembers in CActiveScheduler.\r |
| 193 | */\r |
| 194 | //#define DoStart() DoStart(); friend class CPrivatePolledActiveScheduler;\r |
| 195 | //#include <e32base.h>\r |
| 196 | #include "PolledAS.h"\r |
| 197 | \r |
| 198 | \r |
| 199 | class CPrivatePolledActiveScheduler : public CActiveScheduler\r |
| 200 | {\r |
| 201 | public:\r |
| 202 | void Schedule();\r |
| 203 | };\r |
| 204 | \r |
| 205 | \r |
| 206 | void CPrivatePolledActiveScheduler::Schedule()\r |
| 207 | {\r |
| 208 | TDblQueIter<CActive> q(iActiveQ);\r |
| 209 | q.SetToFirst();\r |
| 210 | FOREVER\r |
| 211 | {\r |
| 212 | CActive *pR=q++;\r |
| 213 | if (pR)\r |
| 214 | {\r |
| 215 | //TRequestStatus::EActive = 1, //bit0\r |
| 216 | //TRequestStatus::ERequestPending = 2, //bit1\r |
| 217 | if (pR->IsActive() && pR->iStatus!=KRequestPending)\r |
| 218 | {\r |
| 219 | // pR->iActive=EFalse; // won't this cause trouble?\r |
| 220 | pR->iStatus.iFlags&=~TRequestStatusFaked::EActive;\r |
| 221 | //debugPrintFile(_L("as: %08x"), pR);\r |
| 222 | TRAPD(r,pR->RunL());\r |
| 223 | //pR->iStatus=TRequestStatus::ERequestPending;\r |
| 224 | break;\r |
| 225 | }\r |
| 226 | }\r |
| 227 | else\r |
| 228 | break;\r |
| 229 | }\r |
| 230 | }\r |
| 231 | \r |
| 232 | \r |
| 233 | static CPolledActiveScheduler* sPolledActiveScheduler = NULL;\r |
| 234 | \r |
| 235 | CPolledActiveScheduler::~CPolledActiveScheduler()\r |
| 236 | {\r |
| 237 | sPolledActiveScheduler = NULL;\r |
| 238 | delete iPrivatePolledActiveScheduler;\r |
| 239 | }\r |
| 240 | \r |
| 241 | CPolledActiveScheduler* CPolledActiveScheduler::NewL()\r |
| 242 | {\r |
| 243 | // if (sPolledActiveScheduler == NULL)\r |
| 244 | {\r |
| 245 | sPolledActiveScheduler = new(ELeave)CPolledActiveScheduler;\r |
| 246 | CleanupStack::PushL(sPolledActiveScheduler);\r |
| 247 | sPolledActiveScheduler->ConstructL();\r |
| 248 | CleanupStack::Pop();\r |
| 249 | }\r |
| 250 | return sPolledActiveScheduler;\r |
| 251 | }\r |
| 252 | \r |
| 253 | void CPolledActiveScheduler::ConstructL()\r |
| 254 | {\r |
| 255 | iPrivatePolledActiveScheduler = new(ELeave) CPrivatePolledActiveScheduler;\r |
| 256 | iPrivatePolledActiveScheduler->Install(iPrivatePolledActiveScheduler);\r |
| 257 | }\r |
| 258 | \r |
| 259 | \r |
| 260 | void CPolledActiveScheduler::Schedule()\r |
| 261 | {\r |
| 262 | iPrivatePolledActiveScheduler->Schedule();\r |
| 263 | }\r |
| 264 | \r |
| 265 | CPolledActiveScheduler* CPolledActiveScheduler::Instance()\r |
| 266 | {\r |
| 267 | // return (CPolledActiveScheduler*) CActiveScheduler::Current();\r |
| 268 | return sPolledActiveScheduler;\r |
| 269 | }\r |