commsfwsupport/commselements/nodemessages/inc/nm_interfaces.h
changeset 0 dfb7c4ff071f
child 18 9644881fedd0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commsfwsupport/commselements/nodemessages/inc/nm_interfaces.h	Thu Dec 17 09:22:25 2009 +0200
@@ -0,0 +1,507 @@
+// Copyright (c) 2006-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
+ @publishedPartner
+ @released
+*/
+
+#ifndef SYMBIAN_NM_INTERFACES_H
+#define SYMBIAN_NM_INTERFACES_H
+
+//#include <elements/nm_signals.h>
+#include <elements/nm_address.h>
+#include <elements/nm_log.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_ElemNodeMessIntH, "ElemNodeMessIntH");
+#endif
+
+namespace Messages
+{
+
+class MTransportSender;
+class ANode;
+class TSignalBase;
+
+
+class TClientType
+/*
+TClientType defines a technology agnostic collection of enums for types and
+flags describing various traits of peers. It is also a placeholder for these
+values. When implementing a relation with a peer, TClientType (or its technology
+specific override) can be used to collect informations about the peers.
+@see RNodeInterface
+*/
+	{
+public:
+    enum TType
+        {
+        //-=============================================
+        //
+        // 1. Types 32bits (a client can only have one type)
+        //
+        //-=============================================
+        EAll            = 0xFFFFFFFF,
+        EUnknown        = 0x00000000,
+        ERegistrar      = 0x00000001, //Useful general purpose role.
+                                      //Used to represent simple non-standard or one-off or transient
+                                      //roles which now do not need to be specially defined for these
+                                      //simple and/or rare relationships.
+        EWorker         = 0x00000002, //Useful general purpose role.
+
+		/**
+		@internalTechnology
+		Reserved types that can change at any time and must NOT be used under any circumstances.
+		Please take care when defining derived client types (do not reference ELastReservedType).
+		*/
+        ELastReservedType_InternalTechnology_CanBeReusedAtAnyTime_DoNotUseInCode = 0x00000080,
+		};
+
+	enum TFlags
+		{
+        //-=============================================
+        //
+        // 2. Flags 32bits (a client can have many flags)
+        //
+        //-=============================================
+        ELeaving        = 0x00000001, //Client has been sent the final goodbye message (e.g TClientLeavingRequest)
+                             //and we are awaiting the channel clear confirmation (e.g. TLeaveComplete).
+                             //No further communication with this client is safe as it assumes we discard
+                             //any references to it. For example it could destruct itself etc.
+		EAdministrative = 0x00000002, //These clients perform some administrative tasks on our node.
+
+		/**
+		@internalTechnology
+		Reserved flags that can change at any time and must NOT be used under any circumstances.
+		Please take care when defining derived client flags (do not reference ELastReservedFlag).
+		*/
+        ELastReservedFlag_InternalTechnology_CanBeReusedAtAnyTime_DoNotUseInCode = 0x00000080
+        };
+
+public:
+	IMPORT_C static const TClientType& NullType();
+
+	TClientType()
+	:	iClientType(EUnknown),
+	    iClientFlags(0)
+		{
+		}
+
+	TClientType(TUint aClientType, TUint aClientFlags = 0)
+	:	iClientType(aClientType),
+		iClientFlags(aClientFlags)
+		{
+		}
+
+	TClientType(const TClientType& aClientType)
+	:	iClientType(aClientType.iClientType),
+		iClientFlags(aClientType.iClientFlags)
+		{
+		}
+
+	TBool IsNull() const
+	    {
+	    return iClientType == 0 && iClientFlags == 0;
+	    }
+
+	TUint32 Type() const
+	    {
+	    return iClientType;
+	    }
+
+	TUint32 Flags() const
+	    {
+	    return iClientFlags;
+	    }
+
+	TUint32 SetFlags(TUint32 aFlags)
+	    {
+	    return iClientFlags |= aFlags;
+	    }
+
+	TUint32 ClearFlags(TUint32 aFlags)
+	    {
+	    return iClientFlags &= ~aFlags;
+	    }
+
+protected:
+    TUint32 iClientType;
+    TUint32 iClientFlags;
+	};
+
+//None of the specified
+struct TNoMatchPolicy
+	{
+	inline static TBool Match(TUint32 aVal, TUint32 aMatch)
+		{
+        return (aVal & aMatch) == 0;
+		}
+	};
+
+//Any of the specified, can be more, can be less
+struct TAnyMatchPolicy
+	{
+	inline static TBool Match(TUint32 aVal, TUint32 aMatch)
+		{
+        return (aVal & aMatch) != 0;
+		}
+	};
+
+//Any of the specified, both can be null, can be more, can be less
+struct TExactOrAnyMatchPolicy
+	{
+	inline static TBool Match(TUint32 aVal, TUint32 aMatch)
+		{
+		return (aVal == aMatch) || (aVal & aMatch) != 0;
+		}
+	};
+
+//All of the specified, can't be more, can be less
+struct TSubSetMatchPolicy
+	{
+	inline static TBool Match(TUint32 aVal, TUint32 aMatch)
+		{
+        return (aVal & aMatch) == aVal;
+		}
+	};
+
+//Any of the specified, can be more, can't be less
+struct TSuperSetMatchPolicy
+	{
+	inline static TBool Match(TUint32 aVal, TUint32 aMatch)
+		{
+        return (aVal & aMatch) == aMatch;
+		}
+	};
+
+//All of the specified, can't be less, can't be more
+struct TExactMatchPolicy
+	{
+	inline static TBool Match(TUint32 aVal, TUint32 aMatch)
+		{
+		return aVal == aMatch;
+		}
+	};
+
+template <typename TTYPEMATCHPOLICY = TSubSetMatchPolicy, typename TFLAGSMATCHPOLICY = TSuperSetMatchPolicy>
+struct TMatchPolicy
+	{
+	inline static TBool Match(const TClientType& aType, const TClientType& aMatch)
+		{
+		return TTYPEMATCHPOLICY::Match(aType.Type(),aMatch.Type())
+			&& TFLAGSMATCHPOLICY::Match(aType.Flags(),aMatch.Flags());
+		}
+	};
+
+template <typename TINCMATCHPOLICY = TMatchPolicy<TSubSetMatchPolicy,TSuperSetMatchPolicy>, typename TEXCMATCHPOLICY = TMatchPolicy<TExactMatchPolicy,TExactMatchPolicy> >
+struct TTypeMatchPolicy
+	{
+	inline static TBool Match(const TClientType& aType, const TClientType& aInclude, const TClientType& aExclude)
+		{
+		TBool inc = TINCMATCHPOLICY::Match(aType, aInclude);
+		TBool exc = aExclude.IsNull() || !TEXCMATCHPOLICY::Match(aType, aExclude);
+		return inc && exc;
+		}
+	};
+
+//We could be using partially specialised typedefs here,
+//if they only were supported by C++ at the time of writing this code...
+//                         INCType   |     Type                  Flag              EXCType    |      Type               Flag
+//                       ----------------------------------------------           -------------------------------------------------
+typedef TTypeMatchPolicy<TMatchPolicy<TSubSetMatchPolicy,  TSuperSetMatchPolicy>, TMatchPolicy<TSuperSetMatchPolicy,TAnyMatchPolicy> > TDefaultClientMatchPolicy;
+typedef TTypeMatchPolicy<TMatchPolicy<TSuperSetMatchPolicy,TSuperSetMatchPolicy>, TMatchPolicy<TSuperSetMatchPolicy,TAnyMatchPolicy> > TFlagsOnlyClientMatchPolicy;
+typedef TTypeMatchPolicy<TMatchPolicy<TSubSetMatchPolicy,  TNoMatchPolicy>,       TMatchPolicy<TSuperSetMatchPolicy,TAnyMatchPolicy> > TExcludeTypeAndFlagClientMatchPolicy;
+typedef TTypeMatchPolicy<TMatchPolicy<TSubSetMatchPolicy, TExactOrAnyMatchPolicy>, TMatchPolicy<TSuperSetMatchPolicy,TAnyMatchPolicy> > TExactOrAnyIncludeFlagsClientMatchPolicy;
+
+
+class RClientInterface
+/*
+Represents an opaque recipient of messages with no assumptions about its
+type (i.e.: it's not necesserilly a node and the only thing known about it, is its
+TRuntimeCtxId). Relations with such recipients should be implemented by declaring
+RClientInterface as members.
+@see RNodeInterface
+*/
+	{
+public:
+	IMPORT_C RClientInterface();
+	IMPORT_C virtual ~RClientInterface(); //Derived types may be used via base ptrs
+	IMPORT_C void Open(const TRuntimeCtxId& aPostTo, MTransportSender* aSender = NULL);
+	IMPORT_C void Close(); // stomp members
+	IMPORT_C TBool operator==(const TRuntimeCtxId& aRHS) const;
+	IMPORT_C TBool operator==(const RClientInterface& aRHS) const;
+
+	IMPORT_C TBool IsOpen() const;
+
+	inline const TRuntimeCtxId& RecipientId() const
+		{
+		return *reinterpret_cast<const TRuntimeCtxId*>(iRecipientAddress);
+		}
+
+	IMPORT_C static void OpenPostMessageClose(const TRuntimeCtxId& aPostFrom, const TRuntimeCtxId& aPostTo, const TSignalBase& aMessage);
+	IMPORT_C void PostMessage(const TRuntimeCtxId& aPostFrom, const TSignalBase& aMessage) const;
+
+protected:
+	void PostMessage(const TRuntimeCtxId& aPostFrom, const TRuntimeCtxId& aPostTo, const TSignalBase& aMessage) const;
+	inline TRuntimeCtxId& RecipientRef()
+		{
+		return *reinterpret_cast<TRuntimeCtxId*>(iRecipientAddress);
+		}
+
+	inline const TRuntimeCtxId& RecipientRef() const
+		{
+		return *reinterpret_cast<const TRuntimeCtxId*>(iRecipientAddress);
+		}
+
+private:
+	MTransportSender* iTransportSender;
+	TUint8 iRecipientAddress[__Align8(TRuntimeCtxId::KMaxInlineAddressSize)];
+	};
+
+
+class RNodeInterface : public RClientInterface
+/*
+RNodeInterface represents a relation with a node (ANode). It does so by:
+- storing the node's address (TNodeId)
+- collecting informations about the node (::Type & ::Flags).
+Classes (typically nodes) should implement relations with another nodes
+by declaring RNodeInterface as members.
+@see TClientType
+*/
+	{
+	friend class TClientIterBase;
+
+public:
+	IMPORT_C void Open(TNodeId aPostTo, const TClientType& aClientType = TClientType::NullType(), MTransportSender* aSender = NULL);
+	IMPORT_C void Close();
+	IMPORT_C TBool operator==(const RNodeInterface& aRHS) const;
+
+	inline TBool operator==(const TRuntimeCtxId& aRHS) const
+		{
+		return RClientInterface::operator==(aRHS);
+		}
+
+	IMPORT_C void PostMessage(const TRuntimeCtxId& aPostFrom, const TNodeId::TRemainder& aPostTo, const TSignalBase& aMessage) const;
+	inline void PostMessage(const TRuntimeCtxId& aPostFrom, const TSignalBase& aMessage) const
+		{
+		#ifdef SYMBIAN_TRACE_ENABLE
+			if(Flags() & TClientType::ELeaving)
+				{
+				NM_LOG_START_BLOCK(KNodeMessagesSubTag, _L8("ERROR: Post while node is leaving"));
+				NM_LOG_ADDRESS_EXT(KNodeMessagesSubTag, aPostFrom, _L8("From:"));
+				NM_LOG_ADDRESS_EXT(KNodeMessagesSubTag, RecipientId(), _L8("To:"));
+				NM_LOG_MESSAGE_EXT(KNodeMessagesSubTag, aMessage, _L8("Msg:"));
+				NM_LOG_END_BLOCK(KNodeMessagesSubTag, KNullDesC8);
+				}
+		#endif
+		__ASSERT_DEBUG(!(Flags() & TClientType::ELeaving), User::Panic(KSpecAssert_ElemNodeMessIntH, 1)); //OOOOOPS! What are you doing??
+		RClientInterface::PostMessage(aPostFrom, aMessage);
+		}
+
+	inline const TNodeId& RecipientId() const
+		{
+		return address_cast<TNodeId>(RClientInterface::RecipientId());
+		}
+
+	TClientType& ClientType()
+		{
+		return iClientType;
+		}
+
+	TUint32 Type() const
+	    {
+	    return iClientType.Type();
+	    }
+
+	TUint32 Flags() const
+	    {
+	    return iClientType.Flags();
+	    }
+
+	TUint32 SetFlags(TUint32 aFlags)
+	    {
+#if defined(_DEBUG) && defined(NM_LOG_FLAG_SETTINGS)
+	    // Note that this generates quite alot of logging, hence is not turned on by default.
+	    // Note also that (a minority of) flag setting may also take place in TNodePeerId.  
+	    const TUint32 oldFlags = Flags();
+	    const TUint32 newFlags = iClientType.SetFlags(aFlags);
+	    if (oldFlags != newFlags)
+	    	{
+	    	NM_LOG((KNodeMessagesSubTag, _L8("RNI::SetFlags(%x) ANode=%08x, %x->%x"), aFlags, &RecipientId().Node(), oldFlags, newFlags));
+	    	}
+	    return newFlags;
+#else
+	    return iClientType.SetFlags(aFlags);
+#endif
+	    }
+
+	TUint32 ClearFlags(TUint32 aFlags)
+	    {
+#if defined(_DEBUG) && defined(NM_LOG_FLAG_SETTINGS)
+	    const TUint32 oldFlags = Flags();
+	    const TUint32 newFlags = iClientType.ClearFlags(aFlags);
+	    if (oldFlags != newFlags)
+	    	{
+	    	NM_LOG((KNodeMessagesSubTag, _L8("RNI::ClearFlags(%x) ANode=%08x, %x->%x"), aFlags, &RecipientId().Node(), oldFlags, newFlags));
+	    	}
+	    return newFlags;
+#else
+	    return iClientType.ClearFlags(aFlags);
+#endif
+	    }
+
+protected:
+	TClientType iClientType;
+	};
+
+class RRequestOriginator
+/*
+RRequestOriginator is a helper class that ackowledges the very common scenario
+where an activity running at a remote node sends a request and that request
+needs to be replied to. RRequestOriginator is associated with a node (holds
+a reference to RNodeInterface) as well as stores the TNodeId::TReminder of
+the address in order to identify the activity running at that node.
+*/
+    {
+public:
+	IMPORT_C TInt Open(RNodeInterface& aNode, const TRuntimeCtxId& aRequestOriginator);
+	IMPORT_C void Open(RRequestOriginator& aOriginalRequest);
+	IMPORT_C void Close();
+
+	IMPORT_C TBool operator==(const RRequestOriginator& aRHS) const;
+	IMPORT_C TBool operator==(const TRuntimeCtxId& aRHS) const;
+
+	IMPORT_C TBool IsOpen() const;
+
+	Messages::RNodeInterface& Node()
+		{
+		__ASSERT_DEBUG(IsOpen(), User::Panic(Messages::KMessagesPanic,Messages::EClientNotValidPanic));
+		return *iNode;
+		}
+	const Messages::RNodeInterface& Node() const
+		{
+		__ASSERT_DEBUG(IsOpen(), User::Panic(Messages::KMessagesPanic,Messages::EClientNotValidPanic));
+		return *iNode;
+		}
+
+	Messages::TNodeId::TRemainder& Remainder()
+		{
+		Node(); //Make sure 'this' is openned
+		return iRemainder;
+		}
+	const Messages::TNodeId::TRemainder& Remainder() const
+		{
+		Node(); //Make sure 'this' is openned
+		return iRemainder;
+		}
+
+
+	IMPORT_C void PostMessage(const TRuntimeCtxId& aPostFrom, const TSignalBase& aMessage) const;
+	IMPORT_C void ReplyTo(const TRuntimeCtxId& aReplyFrom, const TSignalBase& aMessage);
+
+private:
+	Messages::TNodeId::TRemainder iRemainder;
+	Messages::RNodeInterface* 	  iNode;
+    };
+
+//
+// TClientIterBase
+class TClientIterBase
+	{
+public:
+	typedef RPointerArray<RNodeInterface> TClientArray;
+
+public:
+	inline RNodeInterface* operator++(TInt /*aInd*/) //-postfix
+	    {
+	    RNodeInterface* cli = Find(iIndex, +1, 1);
+	    iIndex++;
+	    return cli;
+	    }
+
+	inline RNodeInterface* operator++()              //-prefix
+	    {
+	    ++iIndex;
+	    return Find(iIndex, +1, 1);
+	    }
+
+	inline RNodeInterface* operator--(TInt /*aInd*/) //-postfix
+	    {
+	    RNodeInterface* cli = Find(iIndex, -1, 1);
+	    iIndex--;
+	    return cli;
+	    }
+
+	IMPORT_C RNodeInterface* operator[](TInt aInd);
+
+	inline RNodeInterface* operator*()
+		{
+		return Find(iIndex, +1, 0);
+		}
+
+    void SetToLast()
+        {
+        iIndex = iClients.Count() - 1;
+        }
+
+	void Reset()
+		{
+		iIndex = 0;
+		}
+
+protected:
+	virtual TBool TypeMatch(RNodeInterface& aClient) const = 0;
+	explicit TClientIterBase(const RPointerArray<RNodeInterface>& aClients)
+    :	iClients(aClients),
+    	iIndex(0)
+    	{
+		}
+
+    IMPORT_C RNodeInterface* Find(TInt& aInd, TInt aDir, TInt aCount);
+    const RPointerArray<RNodeInterface>& iClients;
+    TInt iIndex;
+	};
+
+//
+// TClientIter
+template<class TTYPEMATCHPOLICY = TDefaultClientMatchPolicy>
+class TClientIter : public TClientIterBase
+	{
+public:
+	explicit TClientIter(const RPointerArray<RNodeInterface>& aClients, const TClientType& aInclude, const TClientType& aExclude = TClientType::NullType())
+	:	TClientIterBase(aClients), iInclude(aInclude), iExclude(aExclude) {};
+
+private:
+	virtual TBool TypeMatch(RNodeInterface& aClient) const
+		{
+		return TTYPEMATCHPOLICY::Match(aClient.ClientType(), iInclude, iExclude);
+		}
+
+	TClientType iInclude;
+	TClientType iExclude;
+	};
+
+
+} //namespace Messages
+
+#endif
+//SYMBIAN_NM_INTERFACES_H
+
+