cc68a136 |
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 |