commsfwsupport/commselements/meshmachine/inc/mm_states.h
changeset 0 dfb7c4ff071f
equal deleted inserted replaced
-1:000000000000 0:dfb7c4ff071f
       
     1 // Copyright (c) 2007-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 // generic framework node states templates and helper macros
       
    15 // 
       
    16 //
       
    17 
       
    18 /**
       
    19  @file
       
    20  @publishedPartner
       
    21  @released
       
    22 */
       
    23 
       
    24 
       
    25 #ifndef SYMBIAN_MM_STATES_H
       
    26 #define SYMBIAN_MM_STATES_H
       
    27 
       
    28 #include <elements/sm_core.h>
       
    29 #include <elements/mm_context.h>
       
    30 #include <elements/mm_log.h>
       
    31 #include <elements/mm_activities.h> //for AContextStore, logging only
       
    32 #include <elements/nm_signatures.h>
       
    33 
       
    34 
       
    35 #ifdef _DEBUG
       
    36 // Panic category for "absolutely impossible!" vanilla ASSERT()-type panics from this module
       
    37 // (if it could happen through user error then you should give it an explicit, documented, category + code)
       
    38 _LIT(KSpecAssert_ElemMeshMachStaH, "ElemMeshMachStaH");
       
    39 #endif
       
    40 
       
    41 //-=========================================================
       
    42 //
       
    43 // MACROS
       
    44 //
       
    45 //-=========================================================
       
    46 #define DECLARE_SMELEMENT_HEADER(element, base, intf, context) \
       
    47 NONSHARABLE_CLASS(element) : public base \
       
    48 	{ \
       
    49 public:	\
       
    50 	explicit element(context& aContext) : \
       
    51 	    base(aContext) {} \
       
    52 	NETSM_DECLARE_CTR(intf)
       
    53 
       
    54 #define EXPORT_DECLARE_SMELEMENT_HEADER(element, base, intf, context) \
       
    55 class element : public base \
       
    56 	{ \
       
    57 public:	\
       
    58 	explicit element(context& aContext) : \
       
    59 	    base(aContext) {} \
       
    60 	EXPORT_NETSM_DECLARE_CTR(intf) \
       
    61 
       
    62 #define DECLARE_SMELEMENT_FOOTER(element) \
       
    63 	}; \
       
    64 
       
    65 
       
    66 
       
    67 #define DEFINE_SMELEMENT(element, intf, context) \
       
    68 	NETSM_DEFINE_CTR(element, intf, context) \
       
    69 
       
    70 #define EXPORT_DEFINE_SMELEMENT(element, intf, context) \
       
    71 	EXPORT_NETSM_DEFINE_CTR(element, intf, context) \
       
    72 
       
    73 
       
    74 
       
    75 #define DECLARE_AGGREGATED_TRANSITION2(Name, T1, T2) \
       
    76 typedef MeshMachine::TAggregatedTransition<T1, T2, TContext> Name;
       
    77 
       
    78 #define DECLARE_AGGREGATED_TRANSITION3(Name, T1, T2, T3) \
       
    79 DECLARE_AGGREGATED_TRANSITION2(Name##Name__TR3, T1, T2) \
       
    80 DECLARE_AGGREGATED_TRANSITION2(Name, Name##Name__TR3, T3)
       
    81 
       
    82 #define DECLARE_AGGREGATED_TRANSITION4(Name, T1, T2, T3, T4) \
       
    83 DECLARE_AGGREGATED_TRANSITION3(Name##Name__TR4, T1, T2, T3) \
       
    84 DECLARE_AGGREGATED_TRANSITION2(Name, Name##Name__TR4, T4)
       
    85 
       
    86 #define DECLARE_AGGREGATED_TRANSITION5(Name, T1, T2, T3, T4, T5) \
       
    87 DECLARE_AGGREGATED_TRANSITION3(Name##Name__TR5, T1, T2, T3) \
       
    88 DECLARE_AGGREGATED_TRANSITION3(Name, Name##Name__TR5, T4, T5)
       
    89 
       
    90 #define DECLARE_AGGREGATED_TRANSITION6(Name, T1, T2, T3, T4, T5, T6) \
       
    91 DECLARE_AGGREGATED_TRANSITION4(Name##Name__TR6, T1, T2, T3, T4) \
       
    92 DECLARE_AGGREGATED_TRANSITION3(Name, Name##Name__TR6, T5, T6)
       
    93 
       
    94 #define DECLARE_AGGREGATED_TRANSITION7(Name, T1, T2, T3, T4, T5, T6, T7) \
       
    95 DECLARE_AGGREGATED_TRANSITION4(Name##Name__TR7, T1, T2, T3, T4) \
       
    96 DECLARE_AGGREGATED_TRANSITION4(Name, Name##Name__TR7, T5, T6, T7)
       
    97 
       
    98 
       
    99 #define DECLARE_SERIALIZABLE_STATE(Name, Policy, State) \
       
   100 typedef MeshMachine::TSerializableStateFork<Policy, State> Name;
       
   101 
       
   102 #define DECLARE_SERIALIZABLE_STATE_WITH_ERRORTAG(Name, Policy, ErrorTagPolicy, State) \
       
   103 typedef MeshMachine::TSerializableStateFork<Policy, State> Name;
       
   104 
       
   105 #define DECLARE_SERIALIZABLE_TRANSITION(Name, Policy, StateTransition) \
       
   106 typedef MeshMachine::TSerializableTransition<Policy, StateTransition> Name;
       
   107 
       
   108 
       
   109 
       
   110 
       
   111 
       
   112 namespace MeshMachine
       
   113 {
       
   114 
       
   115 //In an (unusual) case where an MState needs to raise
       
   116 //raise an error, it can produce KErrorTag as its
       
   117 //transition tag. The way the actual error code
       
   118 //is conveyed is undefined at this level. It is suggested
       
   119 //to use the context for that. It is herby enforced to
       
   120 //use a naming convention for states that can raise
       
   121 //an error 'E' suffix (e.g.: AwaitSomethingE).
       
   122 const TInt KNoTag                       = NetStateMachine::KExecuteAlways - 3;
       
   123 const TInt KErrorTag                    = NetStateMachine::KExecuteAlways - 4;
       
   124 const TInt KCancelTag                   = NetStateMachine::KExecuteAlways - 5;
       
   125 const TInt KActiveTag                   = NetStateMachine::KExecuteAlways - 6;
       
   126 
       
   127 
       
   128 class AMMNodeBase;
       
   129 typedef MeshMachine::TNodeContext<AMMNodeBase> TContext;
       
   130 
       
   131 //-=========================================================
       
   132 //
       
   133 //Default cancel handling for states
       
   134 //
       
   135 //-=========================================================
       
   136 template <class TCONTEXT>
       
   137 class TState : public NetStateMachine::AContext<TCONTEXT>,
       
   138                public NetStateMachine::MState
       
   139     {
       
   140 public:
       
   141 	NETSM_TPL_DECLARE_CTR(TState, NetStateMachine::MState, TCONTEXT)
       
   142 	typedef TCONTEXT TContext;
       
   143 
       
   144     TState(TCONTEXT& aContext) :
       
   145         NetStateMachine::AContext<TCONTEXT>(aContext)
       
   146         {
       
   147         }
       
   148 
       
   149 	virtual void Cancel()
       
   150         {
       
   151         if (this->iContext.iNodeActivity)
       
   152         	{
       
   153         	this->iContext.iNodeActivity->SetError(KErrCancel);
       
   154         	}
       
   155         }
       
   156     };
       
   157 
       
   158 //-=========================================================
       
   159 //
       
   160 // Default error handling State Transition
       
   161 //
       
   162 //-=========================================================
       
   163 template <class TCONTEXT>
       
   164 class TStateTransition : public NetStateMachine::AContext<TCONTEXT>,
       
   165                          public NetStateMachine::MStateTransition
       
   166     {
       
   167 public:
       
   168 	NETSM_TPL_DECLARE_CTR(TStateTransition, NetStateMachine::MStateTransition, TCONTEXT)
       
   169 	typedef TCONTEXT TContext;
       
   170 
       
   171     TStateTransition(TCONTEXT& aContext) :
       
   172         NetStateMachine::AContext<TCONTEXT>(aContext)
       
   173         {
       
   174         }
       
   175 
       
   176 	virtual void Error( TInt aError )
       
   177 	    {
       
   178         NetStateMachine::AContext<TCONTEXT>::iContext.iReturn = aError;
       
   179         if(NetStateMachine::AContext<TCONTEXT>::iContext.iNodeActivity != NULL)
       
   180         	{
       
   181         	NetStateMachine::AContext<TCONTEXT>::iContext.iNodeActivity->SetError(aError);
       
   182 	        NetStateMachine::AContext<TCONTEXT>::iContext.iNodeActivity->SetIdle(); //By default, set activity to idle
       
   183         	}
       
   184         }
       
   185     };
       
   186 
       
   187 //-=========================================================
       
   188 //
       
   189 //Default state fork
       
   190 //
       
   191 //-=========================================================
       
   192 template <class TCONTEXT>
       
   193 class TStateFork : public NetStateMachine::AContext<TCONTEXT>,
       
   194                    public NetStateMachine::MStateFork
       
   195     {
       
   196 public:
       
   197     NETSM_TPL_DECLARE_CTR(TStateFork, NetStateMachine::MStateTransition, TCONTEXT)
       
   198 	typedef TCONTEXT TContext;
       
   199 
       
   200     TStateFork(TCONTEXT& aContext) :
       
   201         NetStateMachine::AContext<TCONTEXT>(aContext)
       
   202         {
       
   203         }
       
   204 
       
   205 	virtual TInt TransitionTag()
       
   206     	{
       
   207     	return KNoTag | NetStateMachine::EForward;
       
   208     	}
       
   209     };
       
   210 
       
   211 
       
   212 //-=========================================================
       
   213 //
       
   214 //Serializable states & transitions
       
   215 //
       
   216 //-=========================================================
       
   217 template <TInt ERRORTAG>
       
   218 class TStateErrorTransitionTag
       
   219 	{
       
   220 public:
       
   221 	static TInt ErrorTag(const TNodeContextBase& /*aContext*/) { return ERRORTAG; };
       
   222 	};
       
   223 
       
   224 template <class TPOLICY, typename TSTATEFORK, class TERRORTAGPOLICY = TStateErrorTransitionTag<KErrorTag> >
       
   225 class TSerializableStateFork : public TSTATEFORK
       
   226     {
       
   227 public:
       
   228 	typedef typename TSTATEFORK::TContext TContext;
       
   229 
       
   230 	NETSM_TPL_DECLARE_CTR(TSerializableStateFork, NetStateMachine::MStateFork, TContext)
       
   231 
       
   232     TSerializableStateFork(TContext& aContext)
       
   233     :	TSTATEFORK(aContext)
       
   234 		{
       
   235 		}
       
   236 
       
   237 	virtual TInt TransitionTag()
       
   238     	{
       
   239     	if (TPOLICY::IsBlocked(TSTATEFORK::iContext))
       
   240     		{
       
   241     		return (AActivitySemaphore::ParkState(TSTATEFORK::iContext)==KErrNone)?
       
   242     			NetStateMachine::EIgnore : TERRORTAGPOLICY::ErrorTag(TSTATEFORK::iContext);
       
   243     		}
       
   244     	else
       
   245     		{
       
   246 		   	MeshMachine::AActivitySemaphore* as = static_cast<MeshMachine::AActivitySemaphore*>(TSTATEFORK::iContext.iNodeActivity->FetchExtInterface(MeshMachine::AActivitySemaphore::KInterfaceId));
       
   247 			__ASSERT_DEBUG(as, User::Panic(KSpecAssert_ElemMeshMachStaH, 1)); //State/transition mismatched with the activity object (activity doesn't support serialisation - wrong derivation?)
       
   248 
       
   249 			// Log whether the state unparked
       
   250 			if(as->IsWaiting())
       
   251 				{
       
   252 				AActivitySemaphore::UnparkState(TSTATEFORK::iContext);
       
   253 				}
       
   254 
       
   255     		return TSTATEFORK::TransitionTag();
       
   256     		}
       
   257     	}
       
   258     };
       
   259 
       
   260 template <class TPOLICY, typename TSTATETRANSITION>
       
   261 class TSerializableTransition : public TSTATETRANSITION
       
   262     {
       
   263 public:
       
   264 	typedef typename TSTATETRANSITION::TContext TContext;
       
   265 
       
   266 	NETSM_TPL_DECLARE_CTR(TSerializableTransition, NetStateMachine::MStateTransition, TContext)
       
   267 
       
   268     TSerializableTransition(TContext& aContext)
       
   269     :	TSTATETRANSITION(aContext)
       
   270 		{
       
   271 		}
       
   272 
       
   273     virtual void DoL()
       
   274     	{
       
   275    		//If this assertion fires, the serilisable transition has been
       
   276    		//wrongly positioned in the first triple of its activity.
       
   277    		__ASSERT_DEBUG(TSTATETRANSITION::iContext.iNodeActivity, User::Panic(KSpecAssert_ElemMeshMachStaH, 2));
       
   278     	if (TPOLICY::IsBlocked(TSTATETRANSITION::iContext))
       
   279     		{
       
   280     		AActivitySemaphore::ParkTransitionL(TSTATETRANSITION::iContext);
       
   281     		}
       
   282     	else
       
   283     		{
       
   284 #ifdef SYMBIAN_TRACE_ENABLE
       
   285 			// Log whether the transition unparked
       
   286 		   	MeshMachine::AActivitySemaphore* as = static_cast<MeshMachine::AActivitySemaphore*>(TSTATETRANSITION::iContext.iNodeActivity->FetchExtInterface(MeshMachine::AActivitySemaphore::KInterfaceId));
       
   287 			__ASSERT_DEBUG(as, User::Panic(KSpecAssert_ElemMeshMachStaH, 3)); //State/transition mismatched with the activity object (activity doesn't support serialisation - wrong derivation?)
       
   288 			if(as->IsWaiting())
       
   289 				{
       
   290 				MESH_LOG_CONTEXT_EXT(KMeshMachineSubTag, TSTATETRANSITION::iContext, _L8("TSerializableTransition::DoL unparked"));
       
   291 				}
       
   292 #endif
       
   293     		TSTATETRANSITION::DoL();
       
   294     		}
       
   295     	}
       
   296     };
       
   297 
       
   298 //-=========================================================
       
   299 //
       
   300 //Aggregated transitions
       
   301 //
       
   302 //-=========================================================
       
   303 
       
   304 template <class T1, class T2, class TCONTEXT>
       
   305 class TAggregatedTransition : public TStateTransition<TCONTEXT>
       
   306     {
       
   307 public:
       
   308 	NETSM_TPL_DECLARE_CTR(TAggregatedTransition, NetStateMachine::MStateTransition, TCONTEXT)
       
   309 
       
   310     TAggregatedTransition(TCONTEXT& aContext)
       
   311     :	TStateTransition<TCONTEXT>(aContext)
       
   312         {
       
   313         }
       
   314 
       
   315 	virtual void DoL()
       
   316     	{
       
   317     	T1 t1(NetStateMachine::AContext<TCONTEXT>::iContext);
       
   318     	T2 t2(NetStateMachine::AContext<TCONTEXT>::iContext);
       
   319     	t1.DoL();
       
   320     	t2.DoL();
       
   321     	}
       
   322 
       
   323 	virtual void Error(TInt aError)
       
   324     	{
       
   325     	T1 t1(NetStateMachine::AContext<TCONTEXT>::iContext);
       
   326     	T2 t2(NetStateMachine::AContext<TCONTEXT>::iContext);
       
   327     	t1.Error(aError);
       
   328     	t2.Error(aError);
       
   329     	}
       
   330     };
       
   331 
       
   332 //-=========================================================
       
   333 //
       
   334 //Commonly used states
       
   335 //
       
   336 //-=========================================================
       
   337 
       
   338 template<typename TMESSAGE>
       
   339 class TAwaitingMessageState : public MeshMachine::TState<MeshMachine::TContext>
       
   340 	{
       
   341 public:
       
   342 	NETSM_TPL_DECLARE_CTR(TAwaitingMessageState, NetStateMachine::MState, MeshMachine::TContext)
       
   343 
       
   344 	explicit TAwaitingMessageState(MeshMachine::TContext& aContext) :
       
   345 		MeshMachine::TState<MeshMachine::TContext>(aContext) {}
       
   346 
       
   347 	virtual TBool Accept()
       
   348 		{
       
   349 #ifdef __GCCXML__
       
   350 		return EFalse;
       
   351 #else
       
   352 		Messages::TNodeSignal& msg = this->iContext.iMessage; //Arm compiler is getting confused otherwise
       
   353 		return msg.IsMessage<TMESSAGE>();
       
   354 #endif
       
   355 		}
       
   356 	};
       
   357 
       
   358 template<typename TMESSAGE1, class TMESSAGE2>
       
   359 class TAwaiting2MessagesState : public MeshMachine::TState<TContext>
       
   360 	{
       
   361 public:
       
   362 	NETSM_TPL_DECLARE_CTR(TAwaiting2MessagesState, NetStateMachine::MState, TContext)
       
   363 
       
   364 	explicit TAwaiting2MessagesState(TContext& aContext) :
       
   365 		MeshMachine::TState<TContext>(aContext) {}
       
   366 
       
   367 	virtual TBool Accept()
       
   368 			{
       
   369 #ifdef __GCCXML__
       
   370 			return EFalse;
       
   371 #else
       
   372 			Messages::TNodeSignal& msg = this->iContext.iMessage; //Arm compiler is getting confused otherwise
       
   373 			return msg.IsMessage<TMESSAGE1>()
       
   374 				|| msg.IsMessage<TMESSAGE2>();
       
   375 #endif
       
   376 			}
       
   377 	};
       
   378 
       
   379 template<typename TMESSAGE, TUint32 FlagsToSet = 0, TUint32 FlagsToClear = 0>
       
   380 class TAwaitingPeerMessage : public MeshMachine::TState<TContext>
       
   381     {
       
   382 public:
       
   383 	NETSM_TPL_DECLARE_CTR(TAwaitingPeerMessage, NetStateMachine::MState, TContext)
       
   384 
       
   385     TAwaitingPeerMessage(TContext& aContext) :
       
   386         MeshMachine::TState<TContext>(aContext)
       
   387         {
       
   388         }
       
   389 	virtual TBool Accept()
       
   390     	{
       
   391 #ifndef __GCCXML__
       
   392 		Messages::TNodeSignal& msg = this->iContext.iMessage; //Arm compiler is getting confused otherwise
       
   393 		if (msg.IsMessage<TMESSAGE>())
       
   394 			{
       
   395 			__ASSERT_DEBUG(this->iContext.iPeer, User::Panic(KSpecAssert_ElemMeshMachStaH, 4));
       
   396 			this->iContext.iPeer->ClearFlags(FlagsToClear);
       
   397 			this->iContext.iPeer->SetFlags(FlagsToSet);
       
   398 			return ETrue;
       
   399 			}
       
   400 #endif
       
   401 		return EFalse;
       
   402     	}
       
   403     };
       
   404 
       
   405 class AAcceptErrorState
       
   406     {
       
   407 protected:
       
   408 	IMPORT_C static TBool Accept(MeshMachine::TNodeContextBase& aContext, TBool aSuperAccept);
       
   409 	};
       
   410 
       
   411 template<class TSTATE>
       
   412 class TAcceptErrorState  : public TSTATE, public AAcceptErrorState
       
   413     {
       
   414 public:
       
   415 	typedef typename TSTATE::TContext TContext;
       
   416 	NETSM_TPL_DECLARE_CTR(TAcceptErrorState, NetStateMachine::MState, TContext)
       
   417 
       
   418     explicit TAcceptErrorState(TContext& aContext)
       
   419     :	TSTATE(aContext)
       
   420         {
       
   421         }
       
   422 
       
   423 	virtual TBool Accept()
       
   424     	{
       
   425     	return AAcceptErrorState::Accept(this->iContext, TSTATE::Accept());
       
   426     	}
       
   427 
       
   428  	virtual void Cancel()
       
   429         {
       
   430         if(this->iContext.iNodeActivity != NULL)
       
   431         	{
       
   432         	this->iContext.iNodeActivity->SetError(KErrCancel);
       
   433         	}
       
   434         TSTATE::Cancel();
       
   435         }
       
   436     };
       
   437 
       
   438 EXPORT_DECLARE_SMELEMENT_HEADER( TAwaitingNull, TState<TContext>, NetStateMachine::MState, TContext )
       
   439 	IMPORT_C virtual TBool Accept();
       
   440 DECLARE_SMELEMENT_FOOTER( TAwaitingNull )
       
   441 
       
   442 EXPORT_DECLARE_SMELEMENT_HEADER( TAwaitingAny, TState<TContext>, NetStateMachine::MState, TContext )
       
   443 	IMPORT_C virtual TBool Accept();
       
   444 DECLARE_SMELEMENT_FOOTER( TAwaitingAny )
       
   445 
       
   446 EXPORT_DECLARE_SMELEMENT_HEADER( TAwaitingClientLeavingRequest, TState<TContext>, NetStateMachine::MState, TContext )
       
   447 	IMPORT_C virtual TBool Accept();
       
   448 DECLARE_SMELEMENT_FOOTER( TAwaitingClientLeavingRequest )
       
   449 
       
   450 EXPORT_DECLARE_SMELEMENT_HEADER( TAwaitingLeaveComplete, TState<TContext>, NetStateMachine::MState, TContext )
       
   451     IMPORT_C virtual TBool Accept();
       
   452 DECLARE_SMELEMENT_FOOTER( TAwaitingLeaveComplete )
       
   453 
       
   454 EXPORT_DECLARE_SMELEMENT_HEADER( TAwaitingDestroy, TState<TContext>, NetStateMachine::MState, TContext )
       
   455 	IMPORT_C virtual TBool Accept();
       
   456 DECLARE_SMELEMENT_FOOTER( TAwaitingDestroy )
       
   457 
       
   458 EXPORT_DECLARE_SMELEMENT_HEADER( TAwaitingCancel, TState<TContext>, NetStateMachine::MState, TContext )
       
   459 	IMPORT_C virtual TBool Accept();
       
   460 DECLARE_SMELEMENT_FOOTER( TAwaitingCancel )
       
   461 
       
   462 EXPORT_DECLARE_SMELEMENT_HEADER( TAwaitingErrorRecoveryResponseOrError, TState<TContext>, NetStateMachine::MState, TContext )
       
   463 	IMPORT_C virtual TBool Accept();
       
   464 DECLARE_SMELEMENT_FOOTER( TAwaitingErrorRecoveryResponseOrError )
       
   465 
       
   466 //-=========================================================
       
   467 //
       
   468 //Commonly used state forks
       
   469 //
       
   470 //-=========================================================
       
   471 
       
   472 template<TInt TAG>
       
   473 class TTag : public MeshMachine::TStateFork<TContext>
       
   474     {
       
   475 public:
       
   476 	NETSM_TPL_DECLARE_CTR(TTag, NetStateMachine::MStateFork, TContext)
       
   477 
       
   478     TTag(TContext& aContext)
       
   479     :	MeshMachine::TStateFork<TContext>(aContext)
       
   480         {
       
   481         }
       
   482 
       
   483 	virtual TInt TransitionTag()
       
   484     	{
       
   485     	return TAG;
       
   486     	}
       
   487     };
       
   488 
       
   489 template<TInt ACTIVITYSIG>
       
   490 class TActiveOrNoTag  : public MeshMachine::TStateFork<TContext>
       
   491     {
       
   492 public:
       
   493 	NETSM_TPL_DECLARE_CTR(TActiveOrNoTag, NetStateMachine::MStateFork, TContext)
       
   494 
       
   495     explicit TActiveOrNoTag(TContext& aContext)
       
   496     :	MeshMachine::TStateFork<TContext>(aContext)
       
   497         {
       
   498         }
       
   499 
       
   500  	virtual TInt TransitionTag()
       
   501      	{
       
   502 		return (this->iContext.iNode.CountActivities(ACTIVITYSIG))?
       
   503 			MeshMachine::KActiveTag : MeshMachine::KNoTag;
       
   504      	}
       
   505      };
       
   506 
       
   507 class AErrorTagOr
       
   508     {
       
   509 protected:
       
   510 	IMPORT_C static TInt TransitionTag(MeshMachine::TNodeContextBase& aContext);
       
   511 	};
       
   512 
       
   513 template<class TFORK>
       
   514 class TErrorTagOr  : public TFORK, public AErrorTagOr
       
   515     {
       
   516 public:
       
   517 	typedef typename TFORK::TContext TContext;
       
   518 	NETSM_TPL_DECLARE_CTR(TErrorTagOr, NetStateMachine::MStateFork, TContext)
       
   519 
       
   520      explicit TErrorTagOr(TContext& aContext)
       
   521      :	TFORK(aContext)
       
   522         {
       
   523         }
       
   524 
       
   525  	virtual TInt TransitionTag()
       
   526      	{
       
   527      	TUint tag = AErrorTagOr::TransitionTag(this->iContext);
       
   528      	return (tag!=0)? tag : TFORK::TransitionTag();
       
   529      	}
       
   530      };
       
   531 
       
   532 EXPORT_DECLARE_SMELEMENT_HEADER( TNoTag, TStateFork<TContext>, NetStateMachine::MStateFork, TContext )
       
   533 DECLARE_SMELEMENT_FOOTER( TNoTag )
       
   534 
       
   535 EXPORT_DECLARE_SMELEMENT_HEADER( TNoTagBackward, TStateFork<TContext>, NetStateMachine::MStateFork, TContext )
       
   536 	IMPORT_C virtual TInt TransitionTag();
       
   537 DECLARE_SMELEMENT_FOOTER( TNoTagBackward )
       
   538 
       
   539 EXPORT_DECLARE_SMELEMENT_HEADER( TErrorTag, TStateFork<TContext>, NetStateMachine::MStateFork, TContext )
       
   540 	IMPORT_C virtual TInt TransitionTag();
       
   541 DECLARE_SMELEMENT_FOOTER( TErrorTag )
       
   542 
       
   543 EXPORT_DECLARE_SMELEMENT_HEADER( TNoTagOrErrorTag, TStateFork<TContext>, NetStateMachine::MStateFork, TContext )
       
   544 	IMPORT_C virtual TInt TransitionTag();
       
   545 DECLARE_SMELEMENT_FOOTER( TNoTagOrErrorTag )
       
   546 
       
   547 
       
   548 
       
   549 /**
       
   550 This state fork will return KNoTag if no error is present in the activity, or a
       
   551 user supplied tag if an error condition has occured.
       
   552 */
       
   553 template<TInt TAG>
       
   554 NONSHARABLE_CLASS(TNoTagOrCustomErrorTag) : public MeshMachine::TStateFork<TContext>
       
   555     {
       
   556 public:
       
   557     NETSM_TPL_DECLARE_CTR(TNoTagOrCustomErrorTag, NetStateMachine::MStateFork, TContext)
       
   558 
       
   559     TNoTagOrCustomErrorTag(TContext& aContext)
       
   560         : MeshMachine::TStateFork<TContext>(aContext)
       
   561         {
       
   562         }
       
   563 
       
   564     virtual TInt TransitionTag()
       
   565         {
       
   566         Messages::TEBase::TError* msg = Messages::message_cast<Messages::TEBase::TError>(&iContext.iMessage);
       
   567         if (KErrNone==iContext.iNodeActivity->Error() && NULL==msg)
       
   568             {
       
   569             return KNoTag | NetStateMachine::EForward;
       
   570             }
       
   571         if (msg)
       
   572             {
       
   573             iContext.iNodeActivity->SetError(msg->iValue);
       
   574             }
       
   575         return TAG;
       
   576         }
       
   577     };
       
   578 
       
   579 
       
   580 //-=========================================================
       
   581 //
       
   582 // Commonly used transitions
       
   583 //
       
   584 //-=========================================================
       
   585 
       
   586 //RaiseError - this transion, when invoked, just leaves with the error
       
   587 //given as the template parameter.
       
   588 template<TInt ERROR>
       
   589 class TRaiseError : public MeshMachine::TStateTransition<TContext>
       
   590     {
       
   591 public:
       
   592 	NETSM_TPL_DECLARE_CTR(TRaiseError, NetStateMachine::MStateTransition,TContext)
       
   593 
       
   594     TRaiseError(TContext& aContext) :
       
   595         MeshMachine::TStateTransition<TContext>(aContext)
       
   596         {
       
   597         }
       
   598 
       
   599 	virtual void DoL()
       
   600     	{
       
   601     	User::Leave(ERROR);
       
   602     	}
       
   603     };
       
   604 
       
   605 
       
   606 //ARetryTransition - used to turn standard transitions into "retry" ones,
       
   607 //so that they can be used directly in a "retry activity".
       
   608 template<class TSTATETRANSITION, class MESSAGE>
       
   609 class TRetryTransition : public TSTATETRANSITION
       
   610     {
       
   611 public:
       
   612 	typedef typename TSTATETRANSITION::TContext TContext;
       
   613 	NETSM_TPL_DECLARE_CTR(TRetryTransition, NetStateMachine::MStateTransition, TContext)
       
   614 
       
   615     explicit TRetryTransition(TContext& aContext)
       
   616     :	TSTATETRANSITION(aContext)
       
   617         {
       
   618         }
       
   619 
       
   620 	virtual void DoL()
       
   621     	{
       
   622 		__ASSERT_DEBUG(this->iContext.iNodeActivity, User::Panic(KSpecAssert_ElemMeshMachStaH, 5));
       
   623     	MeshMachine::AContextStore* intf = reinterpret_cast<MeshMachine::AContextStore*>(this->iContext.iNodeActivity->FetchExtInterfaceL(MeshMachine::AContextStore::KInterfaceId));
       
   624  		Messages::TNodeSignal::TMessageId retryingFor = intf->RetryingForMessageId();
       
   625  		if (retryingFor.IsNull() || retryingFor == MESSAGE::Id())
       
   626  			{
       
   627  			User::LeaveIfError(intf->StoreContext(this->iContext));
       
   628      		TSTATETRANSITION::DoL();
       
   629      		}
       
   630 		}
       
   631     };
       
   632 
       
   633 //TPostMsgToSender - just posts a reply to the sender of the message being
       
   634 //processed. Only works for SigVoid obviously
       
   635 template<class MESSAGETYPE>
       
   636 class TPostMessageToSender : public MeshMachine::TStateTransition<TContext>
       
   637     {
       
   638 public:
       
   639 	NETSM_TPL_DECLARE_CTR(TPostMessageToSender, NetStateMachine::MStateTransition, TContext)
       
   640 
       
   641     explicit TPostMessageToSender(TContext& aContext)
       
   642     :	MeshMachine::TStateTransition<TContext>(aContext)
       
   643         {
       
   644         }
       
   645 
       
   646 	virtual void DoL()
       
   647     	{
       
   648 		this->iContext.PostToSender(MESSAGETYPE().CRef());
       
   649 		}
       
   650     };
       
   651 
       
   652 //TPostMsgToOriginators - just posts a reply to all originators of the activity
       
   653 //Only works for SigVoid obviously
       
   654 template<class MESSAGETYPE, TUint16 FLAGSTOSET = 0, TUint16 FLAGSTOCLEAR = 0>
       
   655 class TPostMessageToOriginators : public MeshMachine::TStateTransition<TContext>
       
   656     {
       
   657 public:
       
   658 	NETSM_TPL_DECLARE_CTR(TPostMessageToOriginators, NetStateMachine::MStateTransition, TContext)
       
   659 
       
   660     explicit TPostMessageToOriginators(TContext& aContext)
       
   661     :	MeshMachine::TStateTransition<TContext>(aContext)
       
   662         {
       
   663         }
       
   664 
       
   665 	virtual void DoL()
       
   666     	{
       
   667     	__ASSERT_DEBUG(this->iContext.iNodeActivity, User::Panic(KSpecAssert_ElemMeshMachStaH, 6));
       
   668     	this->iContext.iNodeActivity->PostToOriginators(MESSAGETYPE().CRef(), FLAGSTOSET, FLAGSTOCLEAR);
       
   669 		}
       
   670     };
       
   671 
       
   672 EXPORT_DECLARE_SMELEMENT_HEADER( TDoNothing, TStateTransition<TContext>, NetStateMachine::MStateTransition, TContext )
       
   673 	IMPORT_C virtual void DoL();
       
   674 DECLARE_SMELEMENT_FOOTER( TDoNothing )
       
   675 
       
   676 EXPORT_DECLARE_SMELEMENT_HEADER( TSetIdle, TStateTransition<TContext>, NetStateMachine::MStateTransition, TContext )
       
   677 	IMPORT_C virtual void DoL();
       
   678 DECLARE_SMELEMENT_FOOTER( TSetIdle )
       
   679 
       
   680 EXPORT_DECLARE_SMELEMENT_HEADER( TRemoveClient, TStateTransition<TContext>, NetStateMachine::MStateTransition, TContext )
       
   681 	IMPORT_C virtual void DoL();
       
   682 DECLARE_SMELEMENT_FOOTER( TRemoveClient )
       
   683 
       
   684 EXPORT_DECLARE_SMELEMENT_HEADER( TRaiseActivityError, TStateTransition<TContext>, NetStateMachine::MStateTransition, TContext )
       
   685 	IMPORT_C virtual void DoL();
       
   686 DECLARE_SMELEMENT_FOOTER( TRaiseActivityError )
       
   687 
       
   688 EXPORT_DECLARE_SMELEMENT_HEADER( TRaiseAndClearActivityError, TStateTransition<TContext>, NetStateMachine::MStateTransition, TContext )
       
   689 	IMPORT_C virtual void DoL();
       
   690 DECLARE_SMELEMENT_FOOTER( TRaiseAndClearActivityError )
       
   691 
       
   692 EXPORT_DECLARE_SMELEMENT_HEADER( TStoreError, TStateTransition<TContext>, NetStateMachine::MStateTransition, TContext )
       
   693 	IMPORT_C virtual void DoL();
       
   694 DECLARE_SMELEMENT_FOOTER( TStoreError )
       
   695 
       
   696 EXPORT_DECLARE_SMELEMENT_HEADER( TClearError, TStateTransition<TContext>, NetStateMachine::MStateTransition, TContext )
       
   697 	IMPORT_C virtual void DoL();
       
   698 DECLARE_SMELEMENT_FOOTER( TClearError )
       
   699 
       
   700 EXPORT_DECLARE_SMELEMENT_HEADER( TForwardMessageToOriginators, TStateTransition<TContext>, NetStateMachine::MStateTransition, TContext )
       
   701 	IMPORT_C virtual void DoL();
       
   702 DECLARE_SMELEMENT_FOOTER( TForwardMessageToOriginators )
       
   703 
       
   704 } //namespace MeshMachine
       
   705 
       
   706 
       
   707 #endif
       
   708 	// SYMBIAN_MM_STATES_H
       
   709