--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/commsfwsupport/commselements/serverden/inc/sd_thread.h Thu Dec 17 09:22:25 2009 +0200
@@ -0,0 +1,362 @@
+// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+/**
+ @file
+ @internalTechnology
+*/
+
+#ifndef SYMBIAN_DEN_THREAD_H
+#define SYMBIAN_DEN_THREAD_H
+
+#include <cfextras.h>
+#include <cfshared.h>
+#include <elements/cftransport.h>
+
+
+#ifdef _DEBUG
+// Panic category for "absolutely impossible!" vanilla ASSERT()-type panics from this module
+// (if it could happen through user error then you should give it an explicit, documented, category + code)
+_LIT(KSpecAssert_ElemSvrDenThredH, "ElemSvrDenThredH");
+#endif
+
+namespace CommsFW
+{
+struct TCFModuleInfo;
+class TCFBindMsg;
+class TCFUnbindMsg;
+class TCFShutdownMsg;
+class TCFForwardMsg;
+}
+
+namespace Den
+{
+class CWorkerSession;
+class CWorkerRootServChannelHandler;
+class CCommonDealer;
+class CCommonWorkerDealer;
+class CCommonPlayer;
+class CCommonPitBoss;
+class CShutdownWatchDog;
+class CCommonWorkerThread;
+class CPeerDeathNotifier;
+class TPlayerRole;
+class TWorkerIntroductionMsg;
+
+class TWorkerThreadPublicInfo : public CommsFW::TWorkerThreadDataBase
+ {
+public:
+ enum TType
+ {
+ ENullWorkerId = 0xFFFF, //< Non-existent worker
+ EMainThread = 0, //< the Pit Boss and Main Dealer run here
+ EFirstPlayerThread = 1, //< Lowest possible player id
+ EMaxWorkerThreadId = CommsFW::KMaxWorkerId //< Highest possible player id (NB: this is an inclusive bound. Be very careful in array-bound contexts!)
+ };
+
+ //RServer2 iSessionSustainer; //< Used by the PitBoss to keep open a handle to a dealer so it can clean up its resources gracefully before closing the server, if the dealer thread dies.
+ CCommonWorkerThread* iWorker;
+ };
+
+/**
+@class TWorkerThreadRegister
+Structure containing information pertaining to a particular worker thread.
+*/
+NONSHARABLE_CLASS(TWorkerThreadRegister) : public TWorkerThreadPublicInfo
+ {
+ friend class CCommonPitBoss;
+ //friend class CCommonWorkerThread;
+
+public:
+ TWorkerThreadRegister();
+
+private:
+ void Clear();
+ void PeerCleanupPending(CommsFW::TWorkerId aPeerId);
+ void PeerCleanupCompleted(CommsFW::TWorkerId aPeerId);
+ TBool AllPeerCleanupsCompleted() const;
+
+private:
+ CPeerDeathNotifier* iPeerDeathNotifier; //< When the PitBoss binds to the worker thread this will be set up to monitor the thread, in case it dies.
+ TBool iShuttingDown; //< Unused, should be removed.
+ CCommonDealer* iDealer; //< Dealer instance of the worker thread (if exists).
+ CCommonPlayer* iPlayer; //< Player instance of the worker thread (if exists).
+ CommsFW::TCFModuleName iModuleName;
+
+private:
+ /**
+ If a worker thread dies the Pitboss will set a bit corresponding to the dead worker thread ID (/number)
+ in iPendingPeerCleanups in the TWorkerThreadRegister instance for each other worker and send them a TWorkerCleanupDeadPeerMsg.
+ The worker threads will respond by sending TWorkerMsg::ECleanupDeadPeerResp back when they have cleaned up anything
+ related to the dead worker and the PitBoss will reset the bit in their TWorkerThreadRegister instance.
+ @see HandleWorkerCleanupCompletionByPeer()
+ */
+ TUint32 iPendingPeerCleanups;
+
+#ifdef _DEBUG
+ TBool iHasGlobalAllocFails;
+#endif
+ };
+
+typedef CommsFW::CWorkerThreadRegister<TWorkerThreadRegister, CommsFW::KMaxWorkerId> CWorkerRegister;
+
+
+/**
+@class CCommonWorkerThread
+The Worker Thread is the holder of the relevant ESock objects in the CPM instance,
+e.g. the PitBoss, the Dealer and the Player (depending on configuration). It is also
+in charge of inter-thread communication as it holds the object enabling communication
+with the RootServer (CWorkerRootServChannelHandler) and a list of objects for
+communication with other Worker threads (CWorkerTransport).
+
+@see CWorkerRootServChannelHandler
+@see CWorkerTransport
+*/
+class CCommonWorkerThread : public CBase, public CommsFW::MLegacyMessageReceiver
+/**
+@internalComponent
+*/
+ {
+ friend class CWorkerRootServChannelHandler;
+
+public:
+ IMPORT_C ~CCommonWorkerThread();
+
+ /**
+ @return the pointer to the Dealer in this thread. This method might return NULL if the worker thread doesnt have a Dealer.
+ */
+ CCommonDealer* Dealer() const
+ {
+ return iDealer;
+ }
+ IMPORT_C CCommonWorkerDealer* WorkerDealer() const;
+
+ /**
+ @return the pointer to the Player in this thread. This method might return NULL if the worker thread doesnt have a Player.
+ */
+ CCommonPlayer* Player() const
+ {
+ return iPlayer;
+ }
+
+ CommsFW::TWorkerId WorkerId() const
+ {
+ return iWorkerId;
+ }
+
+ Messages::CGlobals& TransportGlobals()
+ {
+ __ASSERT_DEBUG(iGlobals, User::Panic(KSpecAssert_ElemSvrDenThredH, 1));
+ return *iGlobals;
+ }
+
+ /**
+ Return the pointer to the domain PitBoss. This will be initialised when:
+ -# If this is Main thread: In CCommonWorkerThread::ConstructL(TCFModuleInfo* aModuleInfo).
+ -# In other common worker threads: When receiving TWorkerMsg::EMainIntroduction.
+ */
+ CCommonPitBoss& PitBoss() const
+ {
+ __ASSERT_DEBUG(iPitBoss, User::Panic(KSpecAssert_ElemSvrDenThredH, 2));
+ return *iPitBoss;
+ }
+
+ /**
+ Use this to discover whether this Worker Thread is EMainThread ("Esock_Main") which is
+ the main Dealer also containing the PitBoss.
+ @see TWorkerThreadInfo
+ */
+ TBool IsMainThread()
+ {
+ return WorkerId()==TWorkerThreadRegister::EMainThread;
+ }
+
+ TWorkerThreadRegister* WorkerProperties(CommsFW::TWorkerId aWorker)
+ {
+ return iWorkerRegister->GetWorkerGlobals(aWorker);
+ }
+
+ IMPORT_C void SetDealerShutdownComplete(TBool aComplete);
+ TBool DealerShutdownComplete() const
+ {
+ return iDealerShutdownComplete;
+ }
+
+ IMPORT_C void SetPlayerShutdownComplete(TBool aComplete);
+ TBool PlayerShutdownComplete() const
+ {
+ return iPlayerShutdownComplete;
+ }
+
+ IMPORT_C TBool ShuttingDown() const;
+ IMPORT_C void SetShuttingDown();
+ IMPORT_C void SessionShutdownComplete();
+ IMPORT_C void MaybeTriggerThreadShutdownCallback();
+ void TriggerThreadShutdownCallback();
+ IMPORT_C void DestroyDealer();
+ IMPORT_C void DestroyPlayer();
+ void DropTransportToPeer(TInt aPeer);
+ IMPORT_C TBool MaybeCompleteUnbindings();
+
+ // RS control binding processing & message forwarding
+ void CFUnbindMessageReceived(const CommsFW::TCFUnbindMsg& aMsg);
+ void CFShutdownMessageReceived(const CommsFW::TCFShutdownMsg& aMsg);
+
+ // Test whether a message
+ TBool PeerReachable(CommsFW::TWorkerId aPeerId) const
+ {
+ return iTransport->PeerReachable(aPeerId);
+ }
+
+ // Send a message to a peer
+ IMPORT_C void PostMessage(CommsFW::TWorkerId aWorkerId, CommsFW::TCFMessage& aMessage);
+ CommsFW::CCommsTransport* Transport() const
+ {
+ return iTransport;
+ }
+
+ //< Thread nominates self as the default optimal dealer
+ TBool DefaultOptimalDealer() const
+ {
+ return iDefaultOptimalDealer;
+ }
+
+ //
+ IMPORT_C void DispatchL(const CommsFW::TCFMessage& aMessage, CommsFW::TWorkerId aSenderId);
+ virtual TBool DoDispatchL(const CommsFW::TCFMessage& aMessage, CommsFW::TWorkerId aSenderId)=0;
+ IMPORT_C void OnDispatchLeave(const CommsFW::TCFMessage& aMessage, CommsFW::TWorkerId aSenderId, TInt aFirstDispatchLeaveReason);
+
+ // Process a non-internal message from a peer worker. Returns error code
+ IMPORT_C void IncProlongBindingLife();
+ IMPORT_C void DecProlongBindingLife();
+ IMPORT_C void CompleteSessionClose(CWorkerSession* aSession);
+ IMPORT_C void ConstructL(CommsFW::TCFModuleInfo& aModuleInfo, CShutdownWatchDog& aShutdownWatchDog);
+ //Default post mortem cleanup handler
+ IMPORT_C static TInt PostMortemCleanupThreadEntry(TAny* aArg);
+
+protected:
+ virtual CCommonPitBoss* DoCreatePitBossL(CCommonWorkerThread* aWorkerThread)=0;
+ virtual CCommonPlayer* DoCreatePlayerL(CCommonWorkerThread* aWorkerThread, TPlayerRole aPlayerRole)=0;
+ virtual CCommonDealer* DoCreateDealerL(CCommonWorkerThread* aWorkerThread, TPlayerRole aPlayerRole)=0;
+ virtual void DoCompleteUnbinding(CommsFW::TWorkerId aWorker) = 0;
+ virtual void DoSetShuttingDown() = 0;
+ virtual void DoPostMortemCleanup() = 0;
+ virtual void CFBindMessageReceived(const CommsFW::TCFBindMsg& aMsg) = 0;
+ virtual void CFMessageForward(const CommsFW::TCFForwardMsg& aMessage) = 0;
+
+ virtual void DoProcessWorkerIntroductionL(const TWorkerIntroductionMsg& aMessage) = 0;
+
+ IMPORT_C void SendIntroMessage(const CommsFW::TCFModuleName& aPeerName, CommsFW::TWorkerId aPeerId);
+ virtual void DoFillIntroMessage(CommsFW::TWorkerId aPeerId, TWorkerIntroductionMsg& aIntroMsg) = 0;
+
+ IMPORT_C CCommonWorkerThread();
+ IMPORT_C static void DeleteHBufC8(TAny* aHBufC);
+
+ IMPORT_C void DetermineRoleL(HBufC8* aIniData, TBool& aIsDealer, TBool& aIsPlayer, TPlayerRole &aPlayerRole);
+ virtual void DoDeterminePlayerRoleL(HBufC8* aIniData, TPlayerRole &aPlayerRole)=0;
+
+ void ProcessIniDataL();
+ IMPORT_C TInt DecodePeerId(const CommsFW::TCFSubModuleAddress* aSubModule1, const CommsFW::TCFSubModuleAddress* aSubModule2, CommsFW::TWorkerId& aPeerId);
+ IMPORT_C void MaybeCompleteUnbinding(CommsFW::TWorkerId aWorker);
+
+protected:
+ /** This is the handler used for bi-directional communication with the Root Server. */
+ CWorkerRootServChannelHandler* iChannelHandler;
+
+ CWorkerRegister* iWorkerRegister;
+ CommsFW::CCommsTransport* iTransport;
+
+ /**
+ Indentification of this thread. No other instance must have the same id.
+ @see TWorkerThreadInfo
+ */
+ CommsFW::TWorkerId iWorkerId;
+
+ CCommonDealer* iDealer;
+ CCommonPlayer* iPlayer;
+ CCommonPitBoss* iPitBoss;
+
+ TBool iDefaultOptimalDealer;
+
+
+ /** Set when a CommsFW::TCFShutdownMsg is received from the Root Server. */
+ TBool iWorkerShuttingDown;
+
+ /**
+ Set by the Dealer instance to signal to the Worker Thread that it has
+ finished with the shutdown bookkeeping and is ready to be deleted.
+ */
+ TBool iDealerShutdownComplete;
+
+ /**
+ Set by the Player instance to signal to the Worker Thread that it has
+ finished with the shutdown bookkeeping and is ready to be deleted.
+ */
+ TBool iPlayerShutdownComplete;
+
+ /**
+ If the value of this TInt is larger than 0 any unbind requests will not be served,
+ but postponed until iProlongBindingLife is 0. This is to ensure that if e.g. a
+ TWorkerMsg::ECleanupDeadPeer or TPlayerMsg::ESessionClose is received they will be fully
+ served before completing any unbind and thus deleting channel handlers.
+ */
+ TInt iProlongBindingLife;
+
+ CShutdownWatchDog* iShutdownWatchDog;
+ Messages::CGlobals* iGlobals;
+
+public:
+#ifdef _DEBUG
+ RAllocator::TAllocFail AllocFailType() const
+ {
+ return iFailType;
+ }
+ TInt AllocFailRate() const
+ {
+ return iFailRate;
+ }
+#endif
+
+//These must not be conditional (BC)
+private:
+ RAllocator::TAllocFail iFailType;
+ TInt iFailRate;
+ };
+
+NONSHARABLE_CLASS(CShutdownWatchDog) : public CPeriodic
+/**
+@internalComponent
+*/
+ {
+public:
+ IMPORT_C void Shutdown(TBool aImmediate);
+ IMPORT_C static CShutdownWatchDog* NewL(CCommonWorkerThread* aWorker, const TCallBack& aShutDownCb);
+
+private:
+ CShutdownWatchDog(CCommonWorkerThread* aWorker, const TCallBack& aShutDownCb);
+ static TInt TryShutdown(TAny* aSelf);
+
+private:
+ TBool iImmediate;
+ CCommonWorkerThread* iWorker;
+ TCallBack iShutDownCb;
+ };
+
+} //namespace Den
+
+#endif
+//SYMBIAN_DEN_THREAD_H
+
+