commsfwsupport/commselements/StateMachine/src/StateMachine.cpp
changeset 0 dfb7c4ff071f
equal deleted inserted replaced
-1:000000000000 0:dfb7c4ff071f
       
     1 // Copyright (c) 2003-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 // Offers a base class for an asynchronous state machine
       
    15 // 
       
    16 //
       
    17 
       
    18 /**
       
    19  @file 
       
    20 */
       
    21 
       
    22 #include "StateMachine.h"
       
    23 #include "AsynchEvent.h"
       
    24 
       
    25 
       
    26 #ifdef _DEBUG
       
    27 // Panic category for "absolutely impossible!" vanilla ASSERT()-type panics from this module
       
    28 // (if it could happen through user error then you should give it an explicit, documented, category + code)
       
    29 _LIT(KSpecAssert_ElemStateMachStM, "ElemStateMachStM");
       
    30 #endif
       
    31 
       
    32 EXPORT_C CStateMachine::CStateMachine() :
       
    33    CActive( EPriorityStandard )
       
    34    {
       
    35 	CActiveScheduler::Add(this);
       
    36    }
       
    37 
       
    38 EXPORT_C CStateMachine::~CStateMachine()
       
    39    {
       
    40    delete iFragment;
       
    41    }
       
    42 
       
    43 EXPORT_C HBufC8* CStateMachine::ReAllocL( TInt aNewLength )
       
    44 /** 
       
    45  * Re-allocates the instance fragment
       
    46  *
       
    47  * @param aNewLength a length to put into the buffer
       
    48  * @return a pointer to the allocated fragment
       
    49  */
       
    50    {
       
    51    if ( !iFragment )
       
    52       {
       
    53       iFragment = HBufC8::NewL( aNewLength );
       
    54       }
       
    55    else
       
    56       {
       
    57       TInt n = iFragment->Length();
       
    58       if ( (iFragment->Des().MaxLength() - n) < aNewLength )
       
    59          {
       
    60          iFragment = iFragment->ReAllocL( aNewLength + n );
       
    61          }
       
    62       }
       
    63    return iFragment;
       
    64    }
       
    65 
       
    66 EXPORT_C void CStateMachine::Start( TRequestStatus* aClientStatus, CAsynchEvent* aErrorEvent, MStateMachineNotify* aStateMachineNotify )
       
    67 /** 
       
    68  * Starts the state machine
       
    69  *
       
    70  * @param aClientStatus the client request to complete on completion
       
    71  * @param aErrorEvent an error event to execute on error
       
    72  * @param aStateMachineNotify a notifier to receive state achine events
       
    73  */
       
    74    {
       
    75    //history is set beforehand
       
    76    iLastError = KErrNone;
       
    77    iClientStatus = aClientStatus;
       
    78    if (iClientStatus != NULL)
       
    79       *iClientStatus = KRequestPending;
       
    80    iErrorEvent = aErrorEvent;
       
    81    iSuspendRequest = EFalse;
       
    82    iStateMachineNotify = aStateMachineNotify;
       
    83    //jump to RunL
       
    84    TRequestStatus* p=&iStatus;
       
    85    if ( !IsActive() )
       
    86    	{
       
    87 	   SetActive();
       
    88    	}
       
    89    User::RequestComplete( p, KErrNone );
       
    90    }
       
    91 
       
    92 EXPORT_C void CStateMachine::Cancel( TInt aLastError )
       
    93 /** 
       
    94  * Cancels the state machine with an error
       
    95  *
       
    96  * @param aLastError a desired error code. 
       
    97  * if the last eror is KErrNone the state machine
       
    98  * will be cancelled and client request will be completed with KErrCancel.
       
    99  * In any other case the active event will become the error event and the 
       
   100  * processing continues.
       
   101  */
       
   102    {
       
   103    iSuspendRequest = EFalse;
       
   104    if ( aLastError == KErrNone )
       
   105       {
       
   106       iErrorEvent = 0;
       
   107       }
       
   108    //cancel the current activity
       
   109    CActive::Cancel();
       
   110    iLastError = KErrCancel;
       
   111    iActiveEvent = iErrorEvent;
       
   112    if ( iActiveEvent )
       
   113       {
       
   114       //jump to RunL //!!This makes the cancel asynchronous
       
   115       TRequestStatus* p=&iStatus;
       
   116       SetActive();
       
   117       User::RequestComplete( p, KErrNone );
       
   118       }
       
   119    }
       
   120 
       
   121 EXPORT_C void CStateMachine::DoCancel()
       
   122 /** 
       
   123  * completes the cancel request
       
   124  *
       
   125  */
       
   126    {
       
   127    if ( !iErrorEvent ) //otherwise the "cancel" completes after the error event has been sent
       
   128       {
       
   129       OnCompletion();
       
   130       }
       
   131    }
       
   132 
       
   133 EXPORT_C void CStateMachine::OnError()
       
   134 /** 
       
   135  * Called from ::RunL when an error occures
       
   136  *
       
   137  */
       
   138    {
       
   139    if ( iLastError != KErrNone )
       
   140       {
       
   141       if ( iActiveEvent != iErrorEvent )
       
   142          {
       
   143          iActiveEvent = 0;
       
   144          }
       
   145       }
       
   146    else
       
   147       {
       
   148       iLastError = iStatus.Int();
       
   149       iActiveEvent = iErrorEvent;
       
   150       }
       
   151    }
       
   152 
       
   153 EXPORT_C void CStateMachine::RunL()
       
   154 /** 
       
   155  * Called on completion of one active event
       
   156  *
       
   157  */
       
   158    {
       
   159    if ( iStatus.Int() != KErrNone )
       
   160       {//error
       
   161       OnError();
       
   162       }
       
   163    if ( iActiveEvent )
       
   164       {//process iActiveEvent if not iSuspendRequest
       
   165       if ( iSuspendRequest )
       
   166          {
       
   167          if ( iStateMachineNotify )
       
   168             {//return value ignored
       
   169             iStateMachineNotify->OnCompletion( this );
       
   170             }
       
   171          }
       
   172       else
       
   173          {
       
   174          SetActive();
       
   175          iActiveEvent = iActiveEvent->ProcessL( iStatus );
       
   176          }
       
   177       }
       
   178    else
       
   179       {//complete the state machine task
       
   180       OnCompletion();
       
   181       }
       
   182    }
       
   183 
       
   184 EXPORT_C TInt CStateMachine::RunError(TInt aError)
       
   185 /** 
       
   186  * RunL left. Complete status with the aError and let RunL function to handle it
       
   187  *
       
   188  */
       
   189    {
       
   190    //if RunL (ProcessL) leaves the current request must not be completed
       
   191    __ASSERT_DEBUG(IsActive(), User::Panic(KSpecAssert_ElemStateMachStM, 1));
       
   192    iActiveEvent = 0;
       
   193    TRequestStatus* p=&iStatus;
       
   194    User::RequestComplete( p, aError );
       
   195 	return KErrNone; //no error propagation to central error handler
       
   196    }
       
   197 
       
   198 EXPORT_C void CStateMachine::OnCompletion()
       
   199 /** 
       
   200  * Called by RunL when the state machine has completed its task.
       
   201  *
       
   202  */
       
   203    {
       
   204    //!!!notifier cannot delete this
       
   205    TBool bDelete = iStateMachineNotify ? iStateMachineNotify->OnCompletion( this ) : EFalse;
       
   206    if ( iClientStatus )
       
   207       {
       
   208       User::RequestComplete( iClientStatus, iLastError );
       
   209       }
       
   210    if ( bDelete )
       
   211       {
       
   212       delete this;
       
   213       }
       
   214    }
       
   215