|
1 /* |
|
2 * Copyright (c) 2003 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: Combined task arrival observer and task handler manager. |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 |
|
20 #include "taskarrivalobserver.h" |
|
21 #include "taskhandlercreator.h" |
|
22 #include "log.h" |
|
23 |
|
24 CTaskArrivalObserver* CTaskArrivalObserver::NewL() |
|
25 { |
|
26 LOG(Log::Printf(_L("CTaskArrivalObserver::NewL - begin\n"))); |
|
27 CTaskArrivalObserver* self = new (ELeave) CTaskArrivalObserver(); |
|
28 CleanupStack::PushL(self); |
|
29 self->ConstructL(); |
|
30 CleanupStack::Pop(); // self |
|
31 LOG(Log::Printf(_L("CTaskArrivalObserver::NewL - end\n"))); |
|
32 return self; |
|
33 } |
|
34 |
|
35 CTaskArrivalObserver::CTaskArrivalObserver() |
|
36 : CAsyncOneShot(EPriorityNormal) |
|
37 { |
|
38 } |
|
39 |
|
40 void CTaskArrivalObserver::ConstructL() |
|
41 { |
|
42 User::LeaveIfError(iEventMediator.Connect()); |
|
43 iTaskHandlerList = new (ELeave) CArrayPtrFlat<CTaskHandler>(2); |
|
44 iAsyncCleanerList = new (ELeave) CArrayPtrFlat<CAsyncCleaner>(2); |
|
45 } |
|
46 |
|
47 CTaskArrivalObserver::~CTaskArrivalObserver() |
|
48 { |
|
49 LOG(Log::Printf(_L("CTaskArrivalObserver::~CTaskArrivalObserver\n"))); |
|
50 Cancel(); |
|
51 iEventMediator.Close(); |
|
52 if (iTaskHandlerList) |
|
53 { |
|
54 iTaskHandlerList->ResetAndDestroy(); |
|
55 delete iTaskHandlerList; |
|
56 } |
|
57 if (iAsyncCleanerList) |
|
58 { |
|
59 iAsyncCleanerList->ResetAndDestroy(); |
|
60 delete iAsyncCleanerList; |
|
61 } |
|
62 } |
|
63 |
|
64 void CTaskArrivalObserver::Start() |
|
65 { |
|
66 LOG(Log::Printf(_L("CTaskArrivalObserver::Start\n"))); |
|
67 iEventMediator.ListenToEvent(ETaskArrivedEvent, *this); |
|
68 } |
|
69 |
|
70 void CTaskArrivalObserver::Cancel() |
|
71 { |
|
72 LOG(Log::Printf(_L("CTaskArrivalObserver::Cancel\n"))); |
|
73 iEventMediator.CancelListening(ETaskArrivedEvent); |
|
74 } |
|
75 |
|
76 void CTaskArrivalObserver::EventOccured(TInt aStatus, TEventType /*aType*/, TDesC8* aData) |
|
77 { |
|
78 LOG(Log::Printf(_L("CTaskArrivalObserver::EventOccured\n"))); |
|
79 if (aStatus == KErrNone && aData) |
|
80 { |
|
81 LOG(Log::Printf(_L("CTaskArrivalObserver::EventOccured - launching a new task handler\n"))); |
|
82 // The event specification of the task request is delivered |
|
83 // to us as the event data of the task arrivat event |
|
84 TTaskArrivedEventData eventSpec; |
|
85 TPckg<TTaskArrivedEventData> eventSpecDes(eventSpec); |
|
86 eventSpecDes.Copy(*aData); |
|
87 |
|
88 TRAPD(ret, LaunchTaskHandlerL(eventSpec)); |
|
89 |
|
90 // Not being able to create a task handler means that |
|
91 // the client that has issued the corresponding task |
|
92 // request would never be served. This is a fatal error |
|
93 // and not acceptable. Thus, we we need to terminate the |
|
94 // SIT thread in order to notify the Event Mediator and |
|
95 // its clients about problems. |
|
96 if (ret != KErrNone) |
|
97 { |
|
98 CActiveScheduler::Stop(); |
|
99 return; |
|
100 } |
|
101 |
|
102 // Continue observing the |
|
103 // arrival of new tasks |
|
104 Start(); |
|
105 } |
|
106 else |
|
107 { |
|
108 LOG(Log::Printf(_L("CTaskArrivalObserver::EventOccured - stopping the scheduler and thus the SIT\n"))); |
|
109 // We cannot receive new tasks anymore |
|
110 // so the SIT can be terminated |
|
111 CActiveScheduler::Stop(); |
|
112 } |
|
113 } |
|
114 |
|
115 void CTaskArrivalObserver::LaunchTaskHandlerL(const TTaskArrivedEventData& aEventSpec) |
|
116 { |
|
117 LOG(Log::Printf(_L("CTaskArrivalObserver::LaunchTaskHandlerL\n"))); |
|
118 // A new task has arrived so create a task handler for it |
|
119 CTaskHandler* taskHandler = CreateTaskHandlerL(aEventSpec); |
|
120 |
|
121 // Add the handler to the list of active handlers |
|
122 iTaskHandlerList->AppendL(taskHandler); |
|
123 |
|
124 // And start performing the task |
|
125 taskHandler->Start(); |
|
126 } |
|
127 |
|
128 CTaskHandler* CTaskArrivalObserver::CreateTaskHandlerL(const TTaskArrivedEventData& aEventSpec) |
|
129 { |
|
130 LOG(Log::Printf(_L("CTaskArrivalObserver::CreateTaskHandlerL\n"))); |
|
131 CTaskHandler* taskHandler = NULL; |
|
132 |
|
133 taskHandler = TaskHandlerCreator::CreateTaskHandlerL(this, aEventSpec); |
|
134 |
|
135 if (!taskHandler) |
|
136 { |
|
137 User::Panic(KSitName, EPanicUnknownEventType); |
|
138 } |
|
139 |
|
140 return taskHandler; |
|
141 } |
|
142 |
|
143 TInt CTaskArrivalObserver::FindTaskHandler(CTaskHandler* aTaskHandler) |
|
144 { |
|
145 TInt foundIndex = KUnfoundIndex; |
|
146 |
|
147 for (TInt i = 0; i < iTaskHandlerList->Count(); i++) |
|
148 { |
|
149 if (iTaskHandlerList->At(i) == aTaskHandler) |
|
150 { |
|
151 foundIndex = i; |
|
152 break; |
|
153 }; |
|
154 } |
|
155 |
|
156 return foundIndex; |
|
157 } |
|
158 |
|
159 TInt CTaskArrivalObserver::FindAsyncCleaner(CAsyncCleaner* aAsyncCleaner) |
|
160 { |
|
161 TInt foundIndex = KUnfoundIndex; |
|
162 |
|
163 for (TInt i = 0; i < iAsyncCleanerList->Count(); i++) |
|
164 { |
|
165 if (iAsyncCleanerList->At(i) == aAsyncCleaner) |
|
166 { |
|
167 foundIndex = i; |
|
168 break; |
|
169 }; |
|
170 } |
|
171 |
|
172 return foundIndex; |
|
173 } |
|
174 |
|
175 void CTaskArrivalObserver::TaskHandlerComplete(CTaskHandler* aTaskHandler) |
|
176 { |
|
177 LOG(Log::Printf(_L("CTaskArrivalObserver::TaskHandlerComplete\n"))); |
|
178 |
|
179 // In the case several task handlers delete themselves at about the |
|
180 // same time, we need to have a separate cleaner instance for each. |
|
181 // Otherwise we'll get panic E32USER-CBase 42 (SetActive called |
|
182 // while active object is already active). |
|
183 |
|
184 // NOTE. Each asyncCleaner instance will cause itself to be deleted |
|
185 CAsyncCleaner* asyncCleaner = new CAsyncCleaner(this, aTaskHandler); |
|
186 if (asyncCleaner) |
|
187 { |
|
188 // Add the handler to a list of cleaners. This list |
|
189 // is needed to handle some rare cases where the SIT |
|
190 // thread dies before one or more async cleaners get |
|
191 // the chance to delete themselves. Such cleaner |
|
192 // instances get destroyed by the CTaskArrivalObserver |
|
193 // destructor. |
|
194 TRAP_IGNORE(iAsyncCleanerList->AppendL(asyncCleaner)); |
|
195 // Initiate the task handler delete operation |
|
196 asyncCleaner->Start(); |
|
197 } |
|
198 else |
|
199 { |
|
200 // Backup - just in case asyncCleaner could not be created |
|
201 AsyncDeleteTaskHandler(aTaskHandler); |
|
202 } |
|
203 } |
|
204 |
|
205 void CTaskArrivalObserver::AsyncDeleteTaskHandler(CTaskHandler* aTaskHandler) |
|
206 { |
|
207 LOG(Log::Printf(_L("CTaskArrivalObserver::AsyncDeleteTaskHandler\n"))); |
|
208 iTaskHandlerToDelete = aTaskHandler; |
|
209 Call(); |
|
210 } |
|
211 |
|
212 void CTaskArrivalObserver::RunL() // Called as a result of AsyncDeleteTaskHandler |
|
213 { |
|
214 LOG(Log::Printf(_L("CTaskArrivalObserver::RunL\n"))); |
|
215 |
|
216 DeleteTaskHandler(iTaskHandlerToDelete); |
|
217 |
|
218 iTaskHandlerToDelete = NULL; |
|
219 } |
|
220 |
|
221 void CTaskArrivalObserver::DeleteTaskHandler(CTaskHandler* aTaskHandler) |
|
222 { |
|
223 LOG(Log::Printf(_L("CTaskArrivalObserver::DeleteTaskHandler\n"))); |
|
224 |
|
225 // The specified task handler has done its |
|
226 // job succesfully so it can be deleted |
|
227 TInt taskHandlerIndex = FindTaskHandler(aTaskHandler); |
|
228 |
|
229 if (taskHandlerIndex != KUnfoundIndex) |
|
230 { |
|
231 LOG(Log::Printf(_L("CTaskArrivalObserver::DeleteTaskHandler - deleting task handler\n"))); |
|
232 // Delete the task handler |
|
233 delete iTaskHandlerList->At(taskHandlerIndex); |
|
234 // Delete the list item |
|
235 iTaskHandlerList->Delete(taskHandlerIndex); |
|
236 // Deleting elements from the array does not cause |
|
237 // the array buffer to be automatically compressed. |
|
238 // Compress it to return excess space to the heap |
|
239 // as task handlers come and go. |
|
240 iTaskHandlerList->Compress(); |
|
241 } |
|
242 else |
|
243 { |
|
244 // |
|
245 delete aTaskHandler; |
|
246 } |
|
247 } |
|
248 |
|
249 void CTaskArrivalObserver::DeleteAsyncCleaner(CAsyncCleaner* aAsyncCleaner) |
|
250 { |
|
251 LOG(Log::Printf(_L("CTaskArrivalObserver::DeleteAsyncCleaner\n"))); |
|
252 |
|
253 // The specified asynchronous cleaner |
|
254 // has done its job and be deleted |
|
255 TInt asyncCleanerIndex = FindAsyncCleaner(aAsyncCleaner); |
|
256 |
|
257 if (asyncCleanerIndex != KUnfoundIndex) |
|
258 { |
|
259 LOG(Log::Printf(_L("CTaskArrivalObserver::DeleteAsyncCleaner - deleting async cleaner\n"))); |
|
260 // Delete the cleaner object |
|
261 delete iAsyncCleanerList->At(asyncCleanerIndex); |
|
262 // Delete the list item |
|
263 iAsyncCleanerList->Delete(asyncCleanerIndex); |
|
264 // Deleting elements from the array does not cause |
|
265 // the array buffer to be automatically compressed. |
|
266 // Compress it to return excess space to the heap |
|
267 // as cleaner objects come and go. |
|
268 iAsyncCleanerList->Compress(); |
|
269 } |
|
270 else |
|
271 { |
|
272 // Always delete the cleaner instance even |
|
273 // though it have not been added to the list |
|
274 delete aAsyncCleaner; |
|
275 } |
|
276 } |
|
277 |
|
278 void CTaskArrivalObserver::TaskHandlerFatalError(CTaskHandler* /*aTaskHandler*/, TInt /*aError*/) |
|
279 { |
|
280 LOG(Log::Printf(_L("CTaskArrivalObserver::TaskHandlerFatalError - stopping the scheduler and thus the SIT\n"))); |
|
281 // The specified task handler has encountered a fatal error |
|
282 // indicating that it cannot fulfill the task request it was |
|
283 // created to fulfill, meaning that the client that has issued |
|
284 // the corresponding task request would never be served. This |
|
285 // is a fatal error and not acceptable. Thus, we we need to |
|
286 // terminate the SIT thread in order to notify the Event Mediator |
|
287 // and its clients about problems. |
|
288 CActiveScheduler::Stop(); |
|
289 } |
|
290 |
|
291 // CAsyncCleaner |
|
292 |
|
293 CAsyncCleaner::CAsyncCleaner(CTaskArrivalObserver* aTaskArrivalObserver, |
|
294 CTaskHandler* aTaskHandlerToDelete) |
|
295 : CAsyncOneShot(EPriorityNormal), iTaskArrivalObserver(aTaskArrivalObserver), |
|
296 iTaskHandlerToDelete(aTaskHandlerToDelete) |
|
297 { |
|
298 } |
|
299 |
|
300 void CAsyncCleaner::Start() |
|
301 { |
|
302 Call(); |
|
303 } |
|
304 |
|
305 void CAsyncCleaner::RunL() |
|
306 { |
|
307 // Delete the task handler |
|
308 iTaskArrivalObserver->DeleteTaskHandler(iTaskHandlerToDelete); |
|
309 |
|
310 // Delete this cleaner object instance as well |
|
311 iTaskArrivalObserver->DeleteAsyncCleaner(this); |
|
312 } |