commsfwsupport/commselements/serverden/inc/sd_roles.h
changeset 0 dfb7c4ff071f
child 25 9d7ce34704c8
equal deleted inserted replaced
-1:000000000000 0:dfb7c4ff071f
       
     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