|
1 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // THIS WHOLE FILE IS INTERNAL COMPONENT - DO NOT ADD NON-INTERNAL ITEMS |
|
15 // |
|
16 // |
|
17 |
|
18 /** |
|
19 @file |
|
20 @internalComponent |
|
21 */ |
|
22 |
|
23 #ifndef SYMBIAN_DEN_ROLES_H |
|
24 #define SYMBIAN_DEN_ROLES_H |
|
25 |
|
26 #include <e32property.h> |
|
27 #include <elements/sd_std.h> |
|
28 #include <elements/sd_thread.h> |
|
29 #include <elements/interfacetable.h> |
|
30 |
|
31 namespace Den |
|
32 { |
|
33 |
|
34 class CCommonPlayer; |
|
35 class CCommonDealer; |
|
36 class CWorkerSubSession; |
|
37 class TWorkerIntroductionMsg; |
|
38 |
|
39 class CWorkerDataGlobals : public CommsFW::CWorkerThreadDataGlobals<TWorkerThreadRegister, CommsFW::KMaxWorkerId> |
|
40 { |
|
41 public: |
|
42 static CWorkerDataGlobals* NewL() |
|
43 { |
|
44 CWorkerDataGlobals* self = new(ELeave) CWorkerDataGlobals(); |
|
45 CleanupStack::PushL(self); |
|
46 self->ConstructL(sizeof(TWorkerThreadRegister), CommsFW::KMaxWorkerId); |
|
47 CleanupStack::Pop(self); |
|
48 return self; |
|
49 |
|
50 // Because the curr |
|
51 } |
|
52 |
|
53 CCommonWorkerThread* WorkerThread(CommsFW::TWorkerId aWorker) const |
|
54 { |
|
55 return GetWorkerGlobals(aWorker)->iWorker; |
|
56 } |
|
57 }; |
|
58 |
|
59 /** |
|
60 Interface used by the CPeerDeathNotifier to notify a subscriber of thread death. |
|
61 @see CPitBoss |
|
62 */ |
|
63 NONSHARABLE_CLASS(MPeerDeathObserver) |
|
64 { |
|
65 public: |
|
66 virtual void OnPeerDeath(CommsFW::TWorkerId aWorkerId) = 0; |
|
67 }; |
|
68 |
|
69 /** |
|
70 Monitors a worker thread and notifies the observer if it dies. |
|
71 @see RThread::Logon() |
|
72 */ |
|
73 NONSHARABLE_CLASS(CPeerDeathNotifier) : public CActive |
|
74 { |
|
75 public: |
|
76 CPeerDeathNotifier(CommsFW::TWorkerId aWorkerId, RThread aThread, MPeerDeathObserver& aObserver); |
|
77 private: |
|
78 RUndertaker iUndertaker; //< Unused, should be removed |
|
79 private: |
|
80 void DoCancel(); |
|
81 void RunL(); |
|
82 private: |
|
83 CommsFW::TWorkerId iWorkerId; //< The worker id of the thread being monitored. |
|
84 RThread iThread; //< The handle to the thread being monitored. |
|
85 MPeerDeathObserver& iObserver; //< The observer to Notify. |
|
86 }; |
|
87 |
|
88 |
|
89 /** |
|
90 Interface used by the CConfigurationLevelMonitor to notify a subscriber when |
|
91 the Reference Configurator has configured the core components (configuration level == RootServer::ECoreComponentsStarted). |
|
92 @see CPitBoss |
|
93 */ |
|
94 NONSHARABLE_CLASS(MConfiguratorObserver) |
|
95 { |
|
96 public: |
|
97 virtual void OnCPMsConfigured() = 0; |
|
98 virtual TUid PropertyKey()=0; |
|
99 }; |
|
100 |
|
101 /** |
|
102 Subscribes to the configuration level property published by the reference configurator. |
|
103 Calls the subscribed MConfiguratorObserver when the Reference Configurator has configured |
|
104 the core components (configuration level == RootServer::ECoreComponentsStarted). |
|
105 @see CPitBoss |
|
106 */ |
|
107 NONSHARABLE_CLASS(CConfigurationLevelMonitor) : public CActive |
|
108 { |
|
109 public: |
|
110 static CConfigurationLevelMonitor* NewL(MConfiguratorObserver* aObserver); |
|
111 ~CConfigurationLevelMonitor(); |
|
112 protected: |
|
113 CConfigurationLevelMonitor(MConfiguratorObserver* aObserver); |
|
114 void Subscribe(); |
|
115 void RunL(); |
|
116 void DoCancel(); |
|
117 protected: |
|
118 /** The configuration level property published by the reference configurator. |
|
119 */ |
|
120 RProperty iConfLevelProperty; |
|
121 |
|
122 /** The observer waiting for notification that core components have been configured. */ |
|
123 MConfiguratorObserver* iObserver; |
|
124 |
|
125 /** Set ETrue when the level has reached RootServer::ECoreComponentsStarted. |
|
126 Used to ensure the observer is only called once even though the level keeps |
|
127 being published beyond RootServer::ECoreComponentsStarted. |
|
128 */ |
|
129 TBool iCoreComponentsConfigured; |
|
130 }; |
|
131 |
|
132 /** |
|
133 The PitBoss has responsibility for global resources and gross error handling (panics, etc). |
|
134 The Pit Boss thread must be started by the Configurator before any worker threads. The |
|
135 instance loading it must be the only one having the WorkerId 0 (TWorkerThreadInfo::EMainThread). |
|
136 The PitBoss has two main responsibilities: |
|
137 -# Maintain global data structures, accessible to all Workers to which the PitBoss |
|
138 pointer is published (through the TWorkerMainIntroductionMsg). |
|
139 Mostly the workers will access this data using PitBoss access functions which are thread-safe, |
|
140 taking special measures to guarantee this where needed. |
|
141 -# Manage Worker thread start and death: Registering Workers and |
|
142 do a best effort cleanup if they die due to some error condition. |
|
143 |
|
144 Apart from these, the PitBoss also provides some minor but important services. For example as |
|
145 all instances can have their own heap sometimes it happens that one Worker needs to do |
|
146 something that might cause allocation or freeing on another workers heap, such as inserting a |
|
147 sub-session into a Dealers session. So the PitBoss offer a function that can determine whether |
|
148 a different heap is needed (maybe the two workers have different heaps, maybe they share one heap) |
|
149 and does the switch. |
|
150 It also has AddSubSession() and RemoveSubSession() methods used by the Player, assuring this |
|
151 happens on the right heap. |
|
152 */ |
|
153 class CCommonPitBoss : public CBase, |
|
154 public MPeerDeathObserver, |
|
155 public MConfiguratorObserver, |
|
156 public NetInterfaces::TInterfaceControl |
|
157 { |
|
158 friend class TWorkerThreadRegister; |
|
159 public: |
|
160 IMPORT_C ~CCommonPitBoss(); |
|
161 |
|
162 protected: |
|
163 IMPORT_C CCommonPitBoss(CCommonWorkerThread* aOwnerThread); |
|
164 |
|
165 public: |
|
166 IMPORT_C void BindMessageReceived(const CommsFW::TCFModuleName& aPeerName, CommsFW::TWorkerId aPeerId); |
|
167 IMPORT_C void ProcessWorkerIntroductionL(const TWorkerIntroductionMsg& aMsg); |
|
168 IMPORT_C void BroadcastConfigurationComplete(TConfigurationCompletionType aType); |
|
169 |
|
170 IMPORT_C TBool ModuleConfigurationComplete() const; |
|
171 TInt NextSessionId(); |
|
172 |
|
173 IMPORT_C void ConstructL(); |
|
174 |
|
175 IMPORT_C TBool IsShuttingDown() const; |
|
176 void StartShutdown(); |
|
177 IMPORT_C void SessionShutdownComplete(); |
|
178 IMPORT_C TBool FindOptimalDealer(CommsFW::TWorkerId aWorkerId, CCommonWorkerDealer*& aDealer); |
|
179 void ShutdownIfReady(); |
|
180 |
|
181 IMPORT_C void PeerWorkerExiting(CommsFW::TWorkerId aWorker); |
|
182 |
|
183 TBool TestAndLockImmediateShutdownPresent() const; |
|
184 void ReleaseImmediateShutdownPresent() const; |
|
185 void SetImmediateShutdownPresent(); |
|
186 IMPORT_C TBool TestImmediateShutdownPresent() const; |
|
187 |
|
188 CWorkerDataGlobals& WorkerDataGlobals() const |
|
189 { |
|
190 return *iWorkerDataGlobals; |
|
191 } |
|
192 |
|
193 CCommonDealer* Dealer(const TWorkerThreadRegister& aRegister) |
|
194 { |
|
195 return aRegister.iDealer; |
|
196 } |
|
197 |
|
198 CCommonPlayer* Player(const TWorkerThreadRegister& aRegister) |
|
199 { |
|
200 return aRegister.iPlayer; |
|
201 } |
|
202 |
|
203 CCommonWorkerThread* OwnerThread() |
|
204 { |
|
205 return iOwnerThread; |
|
206 } |
|
207 |
|
208 IMPORT_C CCommonDealer* GetDealer(CommsFW::TWorkerId aId); |
|
209 IMPORT_C CCommonPlayer* GetPlayer(const TWorkerIntroductionMsg& aMsg); |
|
210 |
|
211 IMPORT_C void PostMessage(CommsFW::TWorkerId aWorkerId, CommsFW::TCFMessage& aMessage); |
|
212 CCommonDealer* Dealer(CommsFW::TWorkerId aWorkerId) const; |
|
213 CCommonPlayer* Player(CommsFW::TWorkerId aWorkerId) const; |
|
214 inline CCommonWorkerThread& WorkerThread() const; |
|
215 IMPORT_C const RThread& RThreadRef(CommsFW::TWorkerId aWorkerId) const; |
|
216 /** Resolve a Worker thread's CFModule name to its thread id (module names are far less volatile than thread assignments |
|
217 which in the future may become highly dynamic. So module names are used to couple tier ids to threads |
|
218 */ |
|
219 IMPORT_C TBool ResolveWorkerNameToId(const TDesC8& aWorkerName, CommsFW::TWorkerId& aWorkerId) const; |
|
220 /** Resolve a PlayerRole to its thread id (module names are far less volatile than thread assignments |
|
221 which in the future may become highly dynamic. So module names are used to couple tier ids to threads |
|
222 */ |
|
223 IMPORT_C TBool ResolvePlayerRoleToId(const TPlayerRole& aRoleId, CommsFW::TWorkerId& aWorkerId) const; |
|
224 |
|
225 IMPORT_C TBool WorkerExists(CommsFW::TWorkerId aId) const; |
|
226 |
|
227 // Session container manipulation - used by Player |
|
228 IMPORT_C TInt AddSubSession(CWorkerSubSession* aSubSession, CWorkerSession* aSession, TInt& aHandle); |
|
229 IMPORT_C void RemoveSubSession(TInt aHandle, CWorkerSession* aSession); |
|
230 |
|
231 IMPORT_C void HandleWorkerCleanupCompletionByPeer(CommsFW::TWorkerId aWorkerId, CommsFW::TWorkerId aPeerId); |
|
232 void CompleteWorkerThreadCleanup(CommsFW::TWorkerId aWorkerId); |
|
233 |
|
234 // MPeerDeathNotification |
|
235 IMPORT_C void OnPeerDeath(CommsFW::TWorkerId aWorkerId); |
|
236 virtual void DoOnPeerDeath(CommsFW::TWorkerId aWorkerId) = 0; |
|
237 //Defaut RedShirt, uses PostMortemCleanupThreadEntry |
|
238 IMPORT_C virtual TInt DoCreateRedShirt(RThread& aRedShirt, CommsFW::TWorkerId aWorkerId, CCommonWorkerThread& aDeadWorker); |
|
239 |
|
240 // MConfiguratorObserver |
|
241 IMPORT_C void OnCPMsConfigured(); |
|
242 virtual void DoOnCPMsConfigured()=0; |
|
243 |
|
244 TUid PropertyKey() |
|
245 { |
|
246 return iPropertyKey; |
|
247 } |
|
248 |
|
249 inline TSubSessionUniqueId NextSubSessionUniqueId(); |
|
250 inline TSessionUniqueId NextSessionUniqueId(); |
|
251 |
|
252 void FreeWorkerReferences(CommsFW::TWorkerId aWorkerId); |
|
253 |
|
254 IMPORT_C RAllocator* MaybeSwitchHeap(CommsFW::TWorkerId aForeignWorkerId); |
|
255 void AddPendingIntroductionResponse(); |
|
256 void RemovePendingIntroductionResponse(); |
|
257 |
|
258 IMPORT_C void SetFailNextForAllHeaps(TInt aFailNext); |
|
259 IMPORT_C TBool TestFailNextForAllHeaps() const; |
|
260 |
|
261 protected: |
|
262 virtual void DoProcessWorkerIntroductionL(const TWorkerIntroductionMsg& aMsg) = 0; |
|
263 virtual void DoFreeWorkerReferences(CommsFW::TWorkerId aWorkerId) = 0; |
|
264 |
|
265 protected: |
|
266 CCommonWorkerThread* iOwnerThread; |
|
267 CWorkerDataGlobals* iWorkerDataGlobals; |
|
268 /** |
|
269 Incremented when a request to bind to another instance has been received and decremented when a |
|
270 binding is complete. |
|
271 When the reference configurator configuration level have reached the point signifying that all core |
|
272 components have been configured and this TInt is 0, it is safe to delete data structures used only during |
|
273 startup. |
|
274 @see OnCoreComponentsConfigured() |
|
275 */ |
|
276 TInt iPendingIntroResponses; |
|
277 |
|
278 |
|
279 /** |
|
280 ETrue if the PitBoss is in the process of shutting down. Set when optional or graceful shutdown |
|
281 is received by ESock_Main from the RootServer. |
|
282 */ |
|
283 TBool iShuttingDown; |
|
284 |
|
285 /** |
|
286 Set ETrue when immediate shutdown is received by ESock_Main from the RootServer or if |
|
287 optional/graceful shutdown has been received at some point and the last session is closed. |
|
288 */ |
|
289 TBool iSessionShutdownComplete; |
|
290 |
|
291 /** |
|
292 Set ETrue when all Worker threads have finished tidying up during a shut down procedure. |
|
293 The ESock_Main instance will only shut down when this is ETrue. |
|
294 */ |
|
295 TBool iPeerShutdownComplete; |
|
296 |
|
297 /** |
|
298 This is used by Worker threads (as well as ESock_Main) during immediate shutdown. As a Worker |
|
299 could potentially delete a sub-session at the same time as the Dealer trying to mark it orphaned, |
|
300 these two operations need to be protected during immediate shutdown (but not normally). |
|
301 */ |
|
302 mutable RWorkerLock iImmediateShutdownLock; |
|
303 |
|
304 /** |
|
305 Set ETrue when immediate shutdown is received from the RootServer. |
|
306 */ |
|
307 TBool iImmediateShutdownMark; |
|
308 |
|
309 /** |
|
310 Monitor configuration level to know when it is safe to delete data used solely during startup/binding. |
|
311 Note that if we should support loading new Socket Server modules at run time, sometime after system start, |
|
312 this will need to be changed so the list is always available to new modules. |
|
313 */ |
|
314 CConfigurationLevelMonitor* iConfLevelMonitor; |
|
315 |
|
316 /** |
|
317 Session/subsession unique id counter. This value represents a next (free) |
|
318 id that will be assigned to a newly created CWorkerSubSession object. |
|
319 */ |
|
320 TUint iNextUniqueId; |
|
321 TUid iPropertyKey; |
|
322 |
|
323 //TODO: consider if this list is worth having in Den (urel + udeb) or just in esock (urel) |
|
324 //#ifdef _DEBUG |
|
325 // We want to check for leaks whenever a heap is about to be destroyed, however if a thread using |
|
326 // the heap panicked or was killed then this will give false leak indications, so we maintain this |
|
327 // list of heaps known to be "forsaken" in this way. |
|
328 class RForsakenHeapList : private RPointerArray<RAllocator> |
|
329 { |
|
330 public: |
|
331 TInt Add(RAllocator* aHeap) |
|
332 { |
|
333 if(!IsForsaken(aHeap)) |
|
334 { |
|
335 return Append(aHeap); |
|
336 } |
|
337 return KErrNone; |
|
338 } |
|
339 TBool IsForsaken(const RAllocator* aHeap) const |
|
340 { |
|
341 return Find(aHeap) >= 0; |
|
342 } |
|
343 void Close() |
|
344 { |
|
345 RPointerArray<RAllocator>::Close(); |
|
346 } |
|
347 }; |
|
348 RForsakenHeapList iForsakenHeapList; |
|
349 //#endif |
|
350 }; |
|
351 |
|
352 const TInt KResetAllocFails = -73738; |
|
353 |
|
354 /** Helper class for switching the current thread to share that of a peer worker thread. This is necessary for heap manipulating |
|
355 actions such as adding to a container owned by the peer, as well as the more obvious case of deleting an object created by them. |
|
356 Construct a THeapSwitcher instance passing the identity of the peer thread to switch to using their heap. Destroy the THeapSwitcher |
|
357 instance or explicitly call RevertToOwnHeap() to resume using the normal heap for the caller thread. |
|
358 */ |
|
359 class THeapSwitcher |
|
360 { |
|
361 public: |
|
362 IMPORT_C THeapSwitcher(CCommonPitBoss& aPitBoss, const Messages::TNodeId& aTarget); |
|
363 IMPORT_C THeapSwitcher(CCommonPitBoss& aPitBoss, CommsFW::TWorkerId aForeignWorkerId); |
|
364 IMPORT_C ~THeapSwitcher(); |
|
365 IMPORT_C void RevertToOwnHeap(); |
|
366 |
|
367 private: |
|
368 IMPORT_C void MaybeSwitch(CCommonPitBoss& aPitBoss, CommsFW::TWorkerId aForeignWorkerId); |
|
369 RAllocator* iPrev; |
|
370 }; |
|
371 |
|
372 /** |
|
373 The Dealer is an interface to the Symbian OS server (CServer2) and as such one of its most |
|
374 important possessions is the list of CSession2's kept by the CServer2. On a conceptual level |
|
375 one can say that the Dealer owns the CWorkerSession's due to their inherited relationship. |
|
376 Sub-sessions are also supported in the form of the CPlayerSubSession and its derivatives. These are owned |
|
377 by the provider container (CSubSessionIx) in the CWorkerSession. |
|
378 */ |
|
379 class CCommonDealer : public CBase |
|
380 { |
|
381 public: |
|
382 IMPORT_C static CCommonDealer* NewL(CCommonServer* aServer); |
|
383 IMPORT_C ~CCommonDealer(); |
|
384 |
|
385 IMPORT_C const TDesC& ServerName() const; |
|
386 IMPORT_C void DeleteSession(CWorkerSession* aSession); |
|
387 IMPORT_C void CleanupDeadWorker(CommsFW::TWorkerId aPeerId); |
|
388 |
|
389 TInt SubsessionCountInPlayer(CommsFW::TWorkerId aPeerId); |
|
390 |
|
391 TBool CanShutdown() const |
|
392 { |
|
393 return iServer->CanShutdown(); |
|
394 }; |
|
395 |
|
396 CCommonWorkerThread& WorkerThread() |
|
397 { |
|
398 return iServer->WorkerThread(); |
|
399 } |
|
400 |
|
401 CommsFW::TWorkerId WorkerId() const |
|
402 { |
|
403 return iServer->WorkerId(); |
|
404 } |
|
405 |
|
406 /** |
|
407 Returns whether the dealer is the main dealer or not. |
|
408 A main dealer is a dealer which can receive IPC messages directly from a client. |
|
409 Non-main dealers can not, and must have IPC messages handed to them by a main dealer. |
|
410 */ |
|
411 virtual TBool MainDealer() const |
|
412 { |
|
413 return ETrue; |
|
414 } |
|
415 |
|
416 TBool CanUnbindFromWorker(CommsFW::TWorkerId aWorker); |
|
417 IMPORT_C void ProcessConfigurationComplete(TConfigurationCompletionType aType); |
|
418 void ProcessShutdownRequest(CommsFW::TCFShutdownType aType); |
|
419 void ProcessSubSessions(CommsFW::TWorkerId aPeerId, CWorkerSession::TSubSessionProcessor aSubSessionProcessor, TAny* aArg); |
|
420 |
|
421 enum TParkReason |
|
422 { |
|
423 /** During initial configuration a client request may have an indeterminate outcome, in that it relates to a |
|
424 protocol that isn't known but might be yet to load. This would expose clients to the need to cope with a startup race |
|
425 so instead such requests are "parked" until start-up is complete and an authorative answer can be made. |
|
426 */ |
|
427 EIndeterminateDuringBoot, |
|
428 /** The hosting of tier managers by worker threads is only determined upon the first need. The actual work is done by |
|
429 the tier resolver; until this completes all requests needing this are parked |
|
430 */ |
|
431 EAwaitingTierToWorkerMapping, |
|
432 /** Some test cases concern competing client requests, such as a connection start and stop. A test harness can specify that |
|
433 a sequence of requests is parked and then released together. This is only supported when _DEBUG_SOCKET_FUNCTIONS is defined, |
|
434 ie usually only in UDEB |
|
435 */ |
|
436 EDebugParking, |
|
437 }; |
|
438 |
|
439 IMPORT_C TInt ParkRequest(CWorkerSession* aSession, const RMessage2& aMessage, TParkReason aReason) const; // Requests are parked by sessions, which consider servers const |
|
440 |
|
441 #if defined (__ELEMENTS_MESSAGE_INTERCEPT_ACTIVE) |
|
442 void ReleaseDebugParkedRequests(CWorkerSession* aSess, TInt aSubSessHandle); |
|
443 #endif // __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE |
|
444 |
|
445 protected: |
|
446 IMPORT_C CCommonDealer(CCommonServer* aServer); |
|
447 IMPORT_C void ConstructL(); |
|
448 void ReleaseParkedRequests(TParkReason aReason); |
|
449 |
|
450 protected: |
|
451 class TParkedRequest |
|
452 { |
|
453 public: |
|
454 TParkedRequest(CWorkerSession* aSession, const RMessage2& aMessage, TParkReason aReason); |
|
455 public: |
|
456 CWorkerSession* iSession; |
|
457 RMessage2 iMessage; |
|
458 TParkReason iReason; |
|
459 }; |
|
460 |
|
461 typedef RArray<TParkedRequest> RParkedRequestArray; |
|
462 mutable RParkedRequestArray iParkedRequests; |
|
463 CCommonServer* iServer; |
|
464 }; |
|
465 |
|
466 /** |
|
467 All Worker Threads, which are not the main Dealer can contain a Dealer, a Player, or both |
|
468 (often referred to as a DealerPlayer). If the Worker contains a DealerPlayer, the Dealer is |
|
469 also said to be a WorkerDealer or an Optimal Dealer, as clients can create connections directly |
|
470 to it and thus avoid a thread context shift between Dealer and Player when IPC messages are processed. |
|
471 */ |
|
472 NONSHARABLE_CLASS(CCommonWorkerDealer) : public CCommonDealer |
|
473 { |
|
474 protected: |
|
475 static const TInt KMaxEligibleList = 8; //< Maximum length for queue of clients eligible to connect to WorkerDealer |
|
476 |
|
477 public: |
|
478 IMPORT_C static CCommonWorkerDealer* NewL(CCommonServer* aServer); |
|
479 IMPORT_C ~CCommonWorkerDealer(); |
|
480 IMPORT_C void AddEligiblePidL(TProcessId aId); |
|
481 IMPORT_C void RemoveEligiblePid(TProcessId aId); |
|
482 IMPORT_C TBool IsEligible(TProcessId aId); |
|
483 TBool ProcessShutdownRequest(CommsFW::TCFShutdownType aType); |
|
484 |
|
485 /** |
|
486 This dealer is not a main dealer, so return false. It can only receive messages from a main dealer and |
|
487 not directly from a client. |
|
488 |
|
489 @see CCommonDealer::MainDealer |
|
490 */ |
|
491 virtual TBool MainDealer() const |
|
492 { |
|
493 return EFalse; |
|
494 } |
|
495 |
|
496 protected: |
|
497 IMPORT_C explicit CCommonWorkerDealer(CCommonServer* aServer); |
|
498 IMPORT_C void ConstructL(); |
|
499 |
|
500 private: |
|
501 /** |
|
502 CCommonWorkerDealer::XEligibleClients |
|
503 Contains a list of clients eligible to connect to a WorkerDealer. |
|
504 Uses locking in the accessor functions to prevent unpleasant situations. |
|
505 This is an X-class because it has an unusual pattern of being embedded in |
|
506 the containing C-class yet having a necessary ConstructL() and destructor. |
|
507 */ |
|
508 NONSHARABLE_CLASS(XEligibleClients) |
|
509 { |
|
510 public: |
|
511 XEligibleClients(); |
|
512 ~XEligibleClients(); |
|
513 void ConstructL(); |
|
514 void AddL(TProcessId aId); |
|
515 void Remove(TProcessId aId); |
|
516 TBool IsEligible(TProcessId aId); |
|
517 private: |
|
518 /** |
|
519 The list of IDs authorized to create a session directly on this WorkerDealer. |
|
520 @see ::AddL |
|
521 @see ::Remove |
|
522 @see ::IsEligible |
|
523 */ |
|
524 TProcessId iEligibleClients[KMaxEligibleList]; |
|
525 |
|
526 /** |
|
527 Provide atomic access to the list (iEligibleClients) |
|
528 @see ::AddL |
|
529 @see ::Remove |
|
530 */ |
|
531 RWorkerLock iLock; |
|
532 }; |
|
533 |
|
534 private: |
|
535 //RServer2 iSessionSustainer; // Unused, should be removed. |
|
536 XEligibleClients iEligibleClients; //< List of clients eligible to connect to the WorkerDealer. |
|
537 }; |
|
538 |
|
539 /** |
|
540 Represents the session for Player-side actions, such as tracking protocol |
|
541 references and session observers. Has responsibility for handling session |
|
542 close, including signalling close complete back to the Dealer |
|
543 */ |
|
544 class CCommonSessionProxy : public CBase |
|
545 { |
|
546 private: |
|
547 enum { ELivingSession = 0x80000000 }; |
|
548 |
|
549 public: |
|
550 IMPORT_C ~CCommonSessionProxy(); |
|
551 |
|
552 static TInt GetLinkOffset() |
|
553 { |
|
554 return _FOFF(CCommonSessionProxy, iLink); |
|
555 } |
|
556 |
|
557 const CWorkerSession* Session() const |
|
558 { |
|
559 return iSession; |
|
560 } |
|
561 |
|
562 CCommonPlayer& Player() const |
|
563 { |
|
564 return iPlayer; |
|
565 } |
|
566 |
|
567 TBool IsClosing() const |
|
568 { |
|
569 return iNumSubSessClosing != ELivingSession; |
|
570 } |
|
571 |
|
572 void BeginSessionClose(); |
|
573 IMPORT_C void NotifySubSessionDestroyed(); |
|
574 |
|
575 protected: |
|
576 IMPORT_C CCommonSessionProxy(CWorkerSession* aSession, CCommonPlayer& aPlayer); |
|
577 |
|
578 private: |
|
579 CWorkerSession* iSession; //< The session which is represented by proxy instance |
|
580 CCommonPlayer& iPlayer; |
|
581 TInt iNumSubSessClosing; //< Number of subsessions in current thread to complete |
|
582 TDblQueLink iLink; |
|
583 }; |
|
584 |
|
585 /** |
|
586 class CCommonPlayer |
|
587 The main responsibility is adding/removing sub-sessions from the provider container |
|
588 in the related session object as well as keeping a list of all sub-sessions handled |
|
589 by the Player instance (iSubSessions). |
|
590 */ |
|
591 class CCommonPlayer : public CBase |
|
592 { |
|
593 public: |
|
594 typedef RPointerArray<CWorkerSubSession> TSubSessionContainer; |
|
595 |
|
596 public: |
|
597 IMPORT_C ~CCommonPlayer(); |
|
598 |
|
599 IMPORT_C void ProcessMessageL(const RSafeMessage& aMsg, CWorkerSubSession* aSubSession); |
|
600 virtual void DoProcessMessageL(const RSafeMessage& aMsg, CWorkerSubSession* aSubSession) = 0; |
|
601 |
|
602 void PanicClient(CWorkerSubSession& aSubSession, TInt aPanic); |
|
603 void PanicClient(CWorkerSubSession& aSubSession, const TDesC& aCategory, TInt aPanic); |
|
604 IMPORT_C void PanicClient(TInt aPanic); |
|
605 IMPORT_C void PanicClient(const TDesC& aCategory, TInt aPanic); |
|
606 |
|
607 IMPORT_C void CleanupDeadWorker(CommsFW::TWorkerId aPeerId); |
|
608 |
|
609 inline TPlayerRole PlayerRole() const; |
|
610 void SetPlayerRole(const TPlayerRole& aType); |
|
611 |
|
612 inline CCommonWorkerThread& WorkerThread() const; |
|
613 inline CommsFW::CCommsTransport& Transport() const; |
|
614 inline CommsFW::TWorkerId WorkerId() const; |
|
615 inline CCommonPitBoss& PitBoss() const; |
|
616 |
|
617 inline const RSafeMessage& SafeMessage() const; |
|
618 |
|
619 inline CWorkerSession* Session() const; |
|
620 void SetSession(CWorkerSession* aWorkerSession) |
|
621 { |
|
622 iSession=aWorkerSession; |
|
623 } |
|
624 |
|
625 CCommonWorkerThread* OwnerThread() |
|
626 { |
|
627 return iOwnerThread; |
|
628 } |
|
629 |
|
630 inline TSubSessionContainer& SubSessions(); |
|
631 |
|
632 TBool CanUnbindFromWorker(CommsFW::TWorkerId aWorker); |
|
633 |
|
634 IMPORT_C void MaybeSetPlayerShutdownComplete(TBool aForceShutdownNow); |
|
635 virtual TBool IsPlayerShutdownComplete() = 0; |
|
636 |
|
637 void ProcessShutdownRequest(CommsFW::TCFShutdownType aType); |
|
638 |
|
639 IMPORT_C void DontCompleteCurrentRequest(); |
|
640 IMPORT_C TBool ShouldCompleteCurrentRequest() const; |
|
641 |
|
642 IMPORT_C void SetReturn(TInt aReturn); |
|
643 |
|
644 TInt PostMortemCleanup(); |
|
645 |
|
646 IMPORT_C CWorkerSubSession* SubSession(const TSubSessionUniqueId& aSubSessionUniqueId) const; |
|
647 |
|
648 IMPORT_C CCommonSessionProxy* CurrentSessionProxyL(); |
|
649 CCommonSessionProxy* FindOrCreateSessionProxyL(CWorkerSession* aSession); |
|
650 CCommonSessionProxy* FindSessionProxy(CWorkerSession* aSession); |
|
651 |
|
652 protected: |
|
653 IMPORT_C CCommonPlayer(CCommonWorkerThread* aOwnerThread, TPlayerRole aPlayerRole); |
|
654 TInt Return() |
|
655 { |
|
656 return iReturn; |
|
657 } |
|
658 |
|
659 void Reset() |
|
660 { |
|
661 iComplete=ETrue; |
|
662 iReturn=KErrNone; |
|
663 } |
|
664 |
|
665 virtual CCommonSessionProxy* DoCreateSessionProxyL(CWorkerSession* aSession) = 0; |
|
666 |
|
667 private: |
|
668 CCommonWorkerThread* iOwnerThread; //< Thread owning this Player |
|
669 CCommonSessionProxy* iCurrentSessionProxy; //< Current session proxy - only valid within current ProcessL(). |
|
670 TDblQue<CCommonSessionProxy> iSessionProxies; //< All session proxies belonging to this Player |
|
671 CWorkerSession* iSession; //< Current session, which might possibly belong to Dealer in different thread - only valid within current ProcessL(). |
|
672 TSubSessionContainer iSubSessions; //< All sub-sessions belonging to this Player. |
|
673 TPlayerRole iPlayerRole; |
|
674 const RSafeMessage* iCurrentMessage; //< Current RMessage - only valid within current ProcessL(). |
|
675 |
|
676 protected: |
|
677 TBool iComplete; //< Whether to complete the current message at the end of ProcessL() - only valid within current ProcessL(). |
|
678 TInt iReturn; //< Return code to use for completing current RMessage - only valid within current ProcessL(). |
|
679 }; |
|
680 |
|
681 |
|
682 #include <elements/sd_roles.inl> |
|
683 |
|
684 } //namespace Den |
|
685 |
|
686 #endif |
|
687 //SYMBIAN_DEN_ROLES_H |
|
688 |
|
689 |
|
690 |