commsfwsupport/commselements/testing/dummystatelibrary/src/dummyactivities.cpp
changeset 0 dfb7c4ff071f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commsfwsupport/commselements/testing/dummystatelibrary/src/dummyactivities.cpp	Thu Dec 17 09:22:25 2009 +0200
@@ -0,0 +1,285 @@
+// Copyright (c) 2007-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:
+//
+
+
+#include "dummyactivities.h"
+#include "dummystates.h"
+#include "dummymessages.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_ElemTestingdmyct, "ElemTestingdmyct");
+#endif
+
+using namespace Dummy;
+using namespace DummyActivities;
+using namespace DummyStates;
+using namespace Messages;
+using namespace MeshMachine;
+
+
+//(1) CStopActivity constructs itself over the preallocated space
+//(2) CStopActivity preallocates space for only one originator
+//    (as in our demo only the last client triggers the activity)
+class CStopActivity : public MeshMachine::CNodeRetryActivity, protected MeshMachine::APreallocatedOriginators<1>
+	{
+public:
+    static MeshMachine::CNodeActivityBase* New(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode);
+
+protected:
+	CStopActivity(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode)
+	:	CNodeRetryActivity(aActivitySig, aNode),
+		APreallocatedOriginators<1>(iOriginators)
+		{
+		}
+
+	virtual void Destroy();
+	};
+
+//(1) CDestroyActivity constructs itself over the preallocated space
+//(2) CDestroyActivity preallocates space for only one originator
+//    (as in our demo only the host node itself can trigger it)
+class CDestroyActivity : public MeshMachine::CNodeActivityBase, protected MeshMachine::APreallocatedOriginators<1>
+	{
+public:
+    static MeshMachine::CNodeActivityBase* New(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode);
+
+protected:
+	CDestroyActivity(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode)
+	:	CNodeActivityBase(aActivitySig, aNode),
+		APreallocatedOriginators<1>(iOriginators)
+		{
+		}
+
+	virtual void Destroy();
+
+//States, StateForks & StateTransitions specific to the CDestroyActivity
+protected:
+	typedef DummyStates::TContext TContext;
+
+public:
+    DECLARE_SMELEMENT_HEADER( TMarkForDestruction, MeshMachine::TStateTransition<TContext>, NetStateMachine::MStateTransition, TContext )
+    	virtual void DoL();
+    DECLARE_SMELEMENT_FOOTER( TMarkForDestruction )
+private:
+	/*
+	Private NewL with no implementation to hide the CNodeActivityBase::NewL
+	Creation of preallocated activities doesn't fail and hence a non-leaving ::New should be used instead*/
+    static MeshMachine::CNodeActivityBase* NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode);    
+	};
+
+
+namespace CoreErrorActivity
+{
+	typedef DummyStates::TContext TContext;
+
+	DECLARE_SMELEMENT_HEADER( TAwaitingError, MeshMachine::TState<TContext>, NetStateMachine::MState, TContext )
+		virtual TBool Accept();
+	DECLARE_SMELEMENT_FOOTER( TAwaitingError )
+
+	DEFINE_SMELEMENT(TAwaitingError, NetStateMachine::MState, TContext)
+	TBool TAwaitingError::Accept()
+		{
+		if (!iContext.iMessage.IsMessage<TEBase::TError>())
+			{
+			return EFalse;
+			}
+
+	#ifdef _DEBUG
+		//Diagnostic panic only. TError message should not be travelling around with KErrNone.
+		//If you see this panic, please send a proper error code.
+		TEBase::TError& errroMessage = message_cast<TEBase::TError>(iContext.iMessage);
+		__ASSERT_DEBUG(errroMessage.iValue != KErrNone, User::Panic(KSpecAssert_ElemTestingdmyct, 1));
+	#endif
+
+	    return ETrue;
+	    }
+
+	DECLARE_SMELEMENT_HEADER( TProcessError, MeshMachine::TStateTransition<TContext>, NetStateMachine::MStateTransition, TContext )
+		virtual void DoL();
+	DECLARE_SMELEMENT_FOOTER( TProcessError )
+
+	DEFINE_SMELEMENT(TProcessError, NetStateMachine::MStateTransition, TContext)
+	void TProcessError::DoL()
+		{
+		//Find matching activity, if any
+	    CNodeActivityBase* a = iContext.Node().FindAddressedActivity(iContext);
+	    
+	    //We do not allow any unsolicited errors here
+	    __ASSERT_DEBUG(a, User::Panic(KSpecAssert_ElemTestingdmyct, 2));
+
+	    //We are started based on the fact the the last message iContext.Node()'s received is TError
+	    TEBase::TError& errmsg = message_cast<TEBase::TError>(iContext.iMessage);
+	    a->SetError(errmsg.iValue);
+	  	a->SetIdle();
+		}
+}
+
+
+//
+//Activities
+//For more information about single-tripple activities see MeshMachineFundamentals.doc (par. 5.2)
+//For more information about parallel activities see MeshMachineFundamentals.doc (par. TBA)
+
+namespace CoreErrorActivity
+{
+//This activity can not fail.
+//This activity must complete within a single call stack or it would need to be a paralel one.
+//This activity is not cancellable as its actions are irreversible.
+DECLARE_DEFINE_NODEACTIVITY(EActivityError, CoreError, TEBase::TError)
+	NODEACTIVITY_ENTRY(KNoTag, CoreErrorActivity::TProcessError, CoreErrorActivity::TAwaitingError, MeshMachine::TNoTag)
+NODEACTIVITY_END()
+}
+
+namespace DummyNodeJoinActivity
+{
+//This activity does not require the activity object.
+//This activity must complete within a single call stack or it would need to be a paralel one.
+//This activity is cancellable.
+//since every originator wants to be separately added to the client's list.
+//When adding of the client is not successful, the first transition will post a self destruct
+//message to invoke the destroy activity.
+DECLARE_DEFINE_NODEACTIVITY(EActivityClientJoin, DummyNodeJoin, TBindProtocol::TClientJoiningRequest)
+	//TAddClient posts TError to the Client (and TDestroy to the node) if an error occurs.
+	NODEACTIVITY_ENTRY(KNoTag, DummyStates::TCommenceJoinAndAddClientAndPostJoinComplete, DummyStates::TAwaitingClientJoiningRequest, MeshMachine::TNoTag)
+NODEACTIVITY_END()
+}
+
+namespace DummyNodeLeaveActivity
+{
+//This activity can not fail.
+//This activity must complete within a single call stack or it would need to be a paralel one.
+//This activity is not cancellable as its actions are irreversible.
+//This activity does not require the activity object and it does not allocate any memory.
+//It "offloads" the object destruction to the destroy activity.
+DECLARE_DEFINE_NODEACTIVITY(EActivityClientLeave, DummyNodeLeave, TEPeer::TLeaveRequest)
+	NODEACTIVITY_ENTRY(KNoTag, DummyStates::TPostLeaveCompleteAndRemoveClientAndPostDestroyIfLast, MeshMachine::TAwaitingClientLeavingRequest, MeshMachine::TNoTag)
+NODEACTIVITY_END()
+}
+
+namespace DummyNodeStartActivity
+{
+//This activity can fail.
+//This activity is cancellable by its originators.
+//This activity is synchronised with the DummyNodeStop activity.
+DECLARE_DEFINE_CUSTOM_NODEACTIVITY(EActivityStart, DummyNodeStart, TStartProtocol::TStart, CNodeRetryActivity::NewL)
+    FIRST_NODEACTIVITY_ENTRY(DummyStates::TAwaitingStart, DummyStates::TNoTagOrStartedOrNoServiceProviderBlockedByStop)
+	//Started ServiceProvider already present
+	LAST_NODEACTIVITY_ENTRY(KStarted, DummyStates::TPostStarted)
+	//No ServiceProvider present
+	NODEACTIVITY_ENTRY(KNoServiceProvider, DummyStates::TCreateServiceProvider, DummyStates::TAwaitingFactoryObjectCreated, MeshMachine::TTag<KNoServiceProvider>)
+	NODEACTIVITY_ENTRY(KNoServiceProvider, DummyStates::TPostClientJoiningRequest, DummyStates::TAwaitingJoinComplete, MeshMachine::TNoTag)
+	//Non-started ServiceProvider already present
+	//TAddServiceProvider will post TLeaveRequest to the Service Provider should an error occur
+	NODEACTIVITY_ENTRY(KNoTag, DummyStates::TAddServiceProviderAndPostStart, DummyStates::TAwaitingStarted, MeshMachine::TNoTag)
+	LAST_NODEACTIVITY_ENTRY(KNoTag, DummyStates::TPostStarted)
+NODEACTIVITY_END()
+}
+
+namespace DummyNodeStopActivity
+{
+//This activity can not fail but needs the activity object (therefore uses preallocated activity slot).
+//This activity is not cancellable as its actions are irreversible.
+//This activity is synchronised with the DummyNodeStart activity.
+DECLARE_DEFINE_CUSTOM_NODEACTIVITY(EActivityStop, DummyNodeStop, TStopProtocol::TStop, CStopActivity::New)
+	FIRST_NODEACTIVITY_ENTRY(DummyStates::TAwaitingStop, DummyStates::TNoTagOrStartedOrNoServiceProviderBlockedByStart)
+	//Started ServiceProvider present
+	NODEACTIVITY_ENTRY(KStarted, DummyStates::TPostStop, DummyStates::TAwaitingStopped, MeshMachine::TNoTag)
+	//ServiceProvider present
+	NODEACTIVITY_ENTRY(KNoTag, DummyStates::TPostClientLeavingRequest, MeshMachine::TAwaitingLeaveComplete, MeshMachine::TTag<KNoServiceProvider>)
+	//No ServiceProvider present
+	LAST_NODEACTIVITY_ENTRY(KNoServiceProvider, DummyStates::TPostStopped)
+NODEACTIVITY_END()
+}
+
+namespace DummyNodeDestroyActivity
+{
+//For our demonstration purpose this activity implements only an internal protocol
+//(i.e. nodes do not send TDestroy between each other).
+
+//This activity is started when:
+//1) Join request from our only Client fails (plus there are no "outstanding" Clients
+//   who have already taken a handle to this node from the Factory and are about to
+//   send us TClientJoiningRequest),
+//2) The last Client sends us TLeaveRequest (and there are no outstanding
+//   Clients who have already taken a handle to this node from the Factory).
+
+//This activity can not fail but needs the activity object as it will destruct the host node.
+//Destroying activities destroy their hosts when going out of scope.
+DECLARE_DEFINE_CUSTOM_NODEACTIVITY(EActivityDestroy, DummyNodeDestroy, TEChild::TDestroy, CDestroyActivity::New)
+	FIRST_NODEACTIVITY_ENTRY(DummyStates::TAwaitingDestroy, MeshMachine::TNoTag)
+	THROUGH_NODEACTIVITY_ENTRY(KNoTag, CDestroyActivity::TMarkForDestruction, DummyStates::TNoTagOrNoServiceProvider)
+	//The next tripple will loop for as long as there are any Service Providers left
+	NODEACTIVITY_ENTRY(KNoTag, DummyStates::TPostClientLeavingRequest, MeshMachine::TAwaitingLeaveComplete, DummyStates::TNoTagBackwardsOrNoServiceProvider)
+	LAST_NODEACTIVITY_ENTRY(KNoServiceProvider, MeshMachine::TDoNothing)
+NODEACTIVITY_END()
+}
+
+namespace DummyActivities
+{
+DEFINE_EXPORT_ACTIVITY_MAP(dummyActivities)
+	//The error activity must be at the bottom of the activitys' map because
+	//it should see the TError message last, after all of the other activities
+	//got their chances to handle it.
+	ACTIVITY_MAP_ENTRY(CoreErrorActivity, CoreError)
+	ACTIVITY_MAP_ENTRY(DummyNodeJoinActivity, DummyNodeJoin)
+	ACTIVITY_MAP_ENTRY(DummyNodeLeaveActivity, DummyNodeLeave)
+	ACTIVITY_MAP_ENTRY(DummyNodeStartActivity, DummyNodeStart)
+	ACTIVITY_MAP_ENTRY(DummyNodeStopActivity, DummyNodeStop)
+	ACTIVITY_MAP_ENTRY(DummyNodeDestroyActivity, DummyNodeDestroy)
+ACTIVITY_MAP_END()
+}
+
+CNodeActivityBase* CStopActivity::New(const TNodeActivity& aActivitySig, AMMNodeBase& aNode)
+	{
+	TAny* space = BorrowPreallocatedSpace(aNode, sizeof(CStopActivity));
+	CStopActivity* self = new (space) CStopActivity(aActivitySig, aNode);
+	self->AppendPreallocatedActivity(); //Non-destructing preallocated activity
+	return self;
+	}
+
+void CStopActivity::Destroy()
+	{
+	ReturnPreallocatedSpace(this);
+	this->~CStopActivity(); //Run the destructor
+	}
+
+
+CNodeActivityBase* CDestroyActivity::New(const TNodeActivity& aActivitySig, AMMNodeBase& aNode)
+	{
+	TAny* space = BorrowPreallocatedSpace(aNode, sizeof(CDestroyActivity));
+	CDestroyActivity* self = new (space) CDestroyActivity(aActivitySig, aNode);
+	self->InsertPreallocatedDestroyActivity(); //Destructing preallocated activity
+	return self;
+	}
+
+void CDestroyActivity::Destroy()
+	{
+	ReturnPreallocatedSpace(this);
+	this->~CDestroyActivity(); //Run the destructor
+
+	//Delete the provider.
+	static_cast<CTestNodeBase&>(iNode).DeleteMeNow();
+	}
+
+DEFINE_SMELEMENT(CDestroyActivity::TMarkForDestruction, NetStateMachine::MStateTransition, CDestroyActivity::TContext)
+void CDestroyActivity::TMarkForDestruction::DoL()
+	{
+	//Mark the node for deletion, so that it's not served by the factory from now on.
+    iContext.Node().MarkMeForDeletion();
+	}
+