networkprotocolmodules/networkprotocolmodule/LbsProtocolModule/src/cstatemachinebase.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/networkprotocolmodules/networkprotocolmodule/LbsProtocolModule/src/cstatemachinebase.cpp Tue Feb 02 01:50:39 2010 +0200
@@ -0,0 +1,958 @@
+// 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:
+// This file provides the implementation of the base class for
+// protocol state machines used in the Test Protocol Module.
+//
+//
+
+/**
+ @file
+ @internalTechnology
+ @released
+*/
+
+#include "cstatemachinebase.h"
+#include "cstatehandlerbase.h"
+#include "lbsdevloggermacros.h"
+
+//-----------------------------------------------------------------------------
+// State Machine Base Class
+//-----------------------------------------------------------------------------
+
+/** Standard constructor.
+@param aObserver A reference to the state machine observer.
+*/
+CStateMachineBase::CStateMachineBase(MStateMachineObserver& aObserver)
+: CActive(EPriorityLow), iObserver(aObserver), iProtocolState(EStateReady)
+ {
+ ResetSessionId();
+ }
+
+
+/** Standard destructor.
+*/
+CStateMachineBase::~CStateMachineBase()
+ {
+ iCancelSource = ECancelClosing;
+ Cancel();
+ delete iAssistDataTimer;
+ delete iQueue;
+ delete iStateHandler;
+ }
+
+
+/** Retrieve reference to state machine observer.
+@return MStateMachineObserver A reference to the observer.
+*/
+MStateMachineObserver& CStateMachineBase::Observer()
+ {
+ return iObserver;
+ }
+
+/** Set session ID
+@param aSessionId Identifier to be used by the state machine whenever
+ the session ID is to be used.
+*/
+void CStateMachineBase::SessionId(const TLbsNetSessionId& aSessionId)
+ {
+ iSessionId = aSessionId;
+ }
+
+/** Reset session ID
+*/
+void CStateMachineBase::ResetSessionId()
+ {
+ iSessionId.SetSessionOwner(TUid::Uid(0));
+ iSessionId.SetSessionNum(0);
+ }
+
+/** Get session ID
+@return const TLbsNetSessionId& The session ID currently used by the state machine.
+*/
+const TLbsNetSessionId& CStateMachineBase::SessionId() const
+ {
+ return iSessionId;
+ }
+
+/** Set ID for queued session
+@param aSessionId Identifier to be used for a queued session.
+*/
+void CStateMachineBase::QueueSessionId(const TLbsNetSessionId& aSessionId)
+ {
+ iQueueSessionId = aSessionId;
+ }
+
+/** Get ID of queued session
+@return const TLbsNetSessionId& The session ID of the queued session
+*/
+const TLbsNetSessionId& CStateMachineBase::QueueSessionId() const
+ {
+ return iQueueSessionId;
+ }
+
+
+/** Retrieve current general protocol state.
+@return CStateMachineBase::TProtocolState The current general
+ protocol state for this state machine.
+
+@see CStateMachineBase::TProtocolState
+*/
+CStateMachineBase::TProtocolState CStateMachineBase::State() const
+ {
+ return iProtocolState;
+ }
+
+
+/** Start additional assistance data timer.
+The state machine calls this when it has issued a request for additional
+assistance data from the network.
+*/
+void CStateMachineBase::StartAssistDataTimer()
+ {
+ if (iAssistDataTimer->IsActive())
+ {
+ iAssistDataTimer->Cancel();
+ }
+ iAssistDataTimer->EventAfter(TTimeIntervalSeconds(KAssistDataTimerDurationInSec), KAssistDataTimerEvent);
+ }
+
+
+/** Indicates if location request has been received.
+@return TBool ETrue if location request has been received.
+*/
+TBool CStateMachineBase::IsLocReqReceived() const
+ {
+ return iIsLocReqReceived;
+ }
+
+/** Indicates if location response has been sent to network.
+@return TBool ETrue if location response has been sent.
+*/
+TBool CStateMachineBase::IsLocRespSent() const
+ {
+ return iIsLocRespSent;
+ }
+
+/** Indicates if Measurement Control has been handled.
+@return TBool ETrue if Measurement Control has been handled.
+*/
+TBool CStateMachineBase::IsMeasureControlHandled() const
+ {
+ return iIsMeasureControlHandled;
+ }
+
+
+/** Indicates if assistance data action is required.
+@return TBool ETrue if assistance data action is required.
+*/
+TBool CStateMachineBase::IsAssistanceDataActionReq() const
+ {
+ return iAssistanceDataActionRequired;
+ }
+
+
+/** Client close reason.
+This is called by state handlers to determine what reason to
+provide to the client for the client session closing.
+@return TInt Reason value.
+*/
+TInt CStateMachineBase::ClientCloseReason() const
+ {
+ TInt reason = KErrNone;
+
+ if (KErrPositionHighPriorityReceive == iClientCancelReason)
+ {
+ reason = iClientCancelReason;
+ }
+ else if (KErrNone == iNetworkCancelReason)
+ {
+ switch (iCancelSource)
+ {
+ case ECancelNetworkCancel:
+ reason = KErrCancel;
+ break;
+
+ case ECancelNetworkError:
+ reason = KErrDisconnected;
+ break;
+
+ case ECancelClientTimeout:
+ case ECancelNetworkTimeout:
+ reason = KErrTimedOut;
+ break;
+
+ case ECancelNone:
+ {
+ // The reson returned from here is used for teht Session Complete Message from the
+ // Network Gateway to the NRH, so use the value which was received with the location
+ // response
+ reason = LocRespReason();
+ if(reason == KErrCancel || reason == KErrPermissionDenied)
+ {
+ reason = KErrNone;
+ }
+ }
+ break;
+
+ case ECancelClientCancel:
+ reason = iClientCancelReason;
+ break;
+
+ case ECancelClientCancelSilent:
+ case ECancelClosing:
+ break;
+
+ default:
+ User::Panic(KProtocolModulePanic, EProtocolModuleCancelSource);
+ break;
+ };
+ }
+ else
+ {
+ reason = iNetworkCancelReason;
+ }
+
+ return reason;
+ }
+
+
+/** Network close reason.
+This is called by state handlers to determine what reason to
+provide to the network for the network session closing.
+@return TInt Reason value.
+*/
+TInt CStateMachineBase::NetworkCloseReason() const
+ {
+ TInt reason = KErrNone;
+
+ if (KErrPositionHighPriorityReceive == iNetworkCancelReason)
+ {
+ reason = iNetworkCancelReason;
+ }
+ else if (KErrNone == iClientCancelReason)
+ {
+ switch (iCancelSource)
+ {
+ case ECancelClientCancel:
+ case ECancelClientCancelSilent:
+ reason = KErrCancel;
+ break;
+
+ case ECancelClientTimeout:
+ case ECancelNetworkTimeout:
+ reason = KErrTimedOut;
+ break;
+
+ case ECancelNone:
+ case ECancelNetworkCancel:
+ case ECancelNetworkError:
+ case ECancelClosing:
+ break;
+
+ default:
+ User::Panic(KProtocolModulePanic, EProtocolModuleCancelSource);
+ break;
+ };
+ }
+ else
+ {
+ reason = iClientCancelReason;
+ }
+
+ return reason;
+ }
+
+
+/** Silent cancellation of LBS client is taking place.
+This is called by state handlers to determine if there is a silent cancellation
+of the LBS client session taking place, which means that LBS does not receive
+any cancel-related messages for this session.
+@return TBool A value of ETrue indicates silent client cancellation is taking place.
+*/
+TBool CStateMachineBase::IsSilentClientCancel() const
+ {
+ return (ECancelClientCancelSilent == iCancelSource);
+ }
+
+
+/** Network connection error indication.
+This is called by state handlers to determine if a network connection error
+has been experienced. In this situation the state handlers should not attempt
+to send responses to the network.
+@return TBool A value of ETrue indicates a network connection error exists.
+*/
+TBool CStateMachineBase::IsNetworkConnectionError() const
+ {
+ return ((EStateCancelling == iProtocolState) && (ECancelNetworkError == iCancelSource));
+ }
+
+
+/** Location request type.
+This is called by state handlers to determine what type of location
+request is to be specified to LBS. This is usually fixed for a given
+state machine, but there is scope to support more than type of request
+within a single state machine.
+@return MLbsNetworkProtocolObserver::TLbsNetProtocolService request type.
+*/
+MLbsNetworkProtocolObserver::TLbsNetProtocolService CStateMachineBase::LocReqType() const
+ {
+ return iLocReqType;
+ }
+
+
+/** Location response reason.
+This is called by state handlers to determine what reason to
+provide to the network for the location response failure.
+@return TInt Reason value.
+*/
+TInt CStateMachineBase::LocRespReason() const
+ {
+ TInt reason = KErrNone;
+ // Was a Location response error provided?
+ if (KErrNone != iLocRespReason)
+ {
+ reason = iLocRespReason;
+ }
+ // Are we cancelling?
+ else if (Cancelling())
+ {
+ switch (iCancelSource)
+ {
+ case ECancelClientCancel:
+ case ECancelClientCancelSilent:
+ if (KErrPositionHighPriorityReceive == iClientCancelReason)
+ {
+ reason = iClientCancelReason;
+ }
+ else
+ {
+ reason = KErrCancel;
+ }
+ break;
+
+ case ECancelClientTimeout:
+ reason = KErrGeneral;
+ break;
+
+ case ECancelNone:
+ case ECancelNetworkError:
+ case ECancelNetworkTimeout:
+ case ECancelNetworkCancel:
+ case ECancelClosing:
+ break;
+
+ default:
+ User::Panic(KProtocolModulePanic, EProtocolModuleCancelSource);
+ break;
+
+ };
+ }
+ return reason;
+ }
+
+
+/** Location response position.
+This is called by state handlers to retrieve the most
+recent reported position.
+@return TPositionInfoBase Currently held location response position
+*/
+const TPositionInfoBase& CStateMachineBase::LocRespPosition() const
+ {
+ return iLocRespPosInfo;
+ }
+
+
+/** Reference Location.
+This is called by state handlers to retrieve the most
+recent reported reference location.
+@return TPositionInfoBase Currently held reference position
+*/
+const TPositionInfoBase& CStateMachineBase::ReferenceLoc() const
+ {
+ return iReferenceLoc;
+ }
+
+
+/** Location request quality.
+This is called by state handlers to retrieve the most
+recent location request quality.
+@return TLbsNetPosRequestQuality Currently held location request quality
+*/
+const TLbsNetPosRequestQuality& CStateMachineBase::LocReqQuality() const
+ {
+ return iLocReqQuality;
+ }
+
+
+/** Location request positioning method.
+This is called by state handlers to retrieve the most
+recent location request positioning method.
+@return TLbsNetPosRequestMethod Currently held location request positioning method
+*/
+const TLbsNetPosRequestMethod& CStateMachineBase::PosMethod() const
+ {
+ return iPosMethod;
+ }
+
+
+/** Initialise internal state machine attributes.
+This is used when a new protocol procedure commences.
+*/
+void CStateMachineBase::InitialiseMachineBase()
+ {
+ iTransitionState = ETransitionNull;
+ iIsCancelPending = EFalse;
+ iCancelSource = ECancelNone;
+ iClientCancelReason = KErrNone;
+ iNetworkCancelReason = KErrNone;
+ iIsLocReqReceived = EFalse;
+ iIsLocRespSent = EFalse;
+ iIsMeasureControlHandled = EFalse;
+ iIsAdditionalDataExpected = EFalse;
+ iAssistanceDataActionRequired = EFalse;
+ iLocRespReason = KErrNone;
+
+ LBSLOG(ELogP2, "CStateMachineBase::InitialiseMachineBase() protocol state ---> EStateActive \n");
+ iProtocolState = EStateActive;
+ iIsMachineQueued = EFalse;
+ }
+
+
+/** Complete state machine attributes.
+This is used when a protocol procedure completes.
+*/
+void CStateMachineBase::CompleteMachineBase()
+ {
+ LBSLOG(ELogP2, "CStateMachineBase::CompleteMachineBase() protocol state ---> EStateReady\n");
+ iProtocolState = EStateReady;
+ // Inform Protocol Manager that procedure is complete
+ Observer().ProcedureCompleteInd();
+ }
+
+
+/** Store location response.
+@param aPosInfo Location information response
+*/
+void CStateMachineBase::StoreLocationResp(TInt aReason, const TPositionInfoBase& aPosInfo)
+ {
+ iLocRespReason = aReason;
+ iLocRespPosInfo = reinterpret_cast <const TPositionInfo&> (aPosInfo);
+ }
+
+
+/** Store network location cancel reason.
+@param aReason The reason for cancelling network location
+*/
+void CStateMachineBase::StoreNetLocCancelReason(TInt aReason)
+ {
+ iNetLocCancelReason = aReason;
+ }
+
+
+/** Store location request quality
+@param aQuality Location request quality
+*/
+void CStateMachineBase::StoreLocReqQuality(const TLbsNetPosRequestQuality& aQuality)
+ {
+ iLocReqQuality = aQuality;
+ }
+
+
+/** Store location request positioning method
+@param aPosMethod Location request positioning method
+*/
+void CStateMachineBase::StorePosMethod(const TLbsNetPosRequestMethod& aPosMethod)
+ {
+ iPosMethod = aPosMethod;
+ }
+
+
+/** Store reference location
+@param aPosInfo Network reference location information
+*/
+void CStateMachineBase::StoreRefLoc(const TPositionInfoBase& aPosInfo)
+ {
+ iReferenceLoc = reinterpret_cast <const TPositionInfo&> (aPosInfo);
+ }
+
+
+/** Enter new state.
+This asks the state handler to perform the actions required when
+entering a new state.
+*/
+void CStateMachineBase::EnterNewState()
+ {
+ ASSERT(iStateHandler != NULL);
+
+ // Perform entry actions for the new state
+ iStateHandler->EntryActions();
+ }
+
+
+/** Exit current state.
+This asks the state handler to perform the actions required when
+exiting from a state.
+*/
+void CStateMachineBase::ExitCurrentState()
+ {
+ ASSERT(iStateHandler != NULL);
+
+ // Perform exit actions for the current state
+ iStateHandler->ExitActions();
+ }
+
+
+/** Perform a state transition.
+This initiates a state transition and performs the first stage of
+this by exiting from the current state.
+*/
+void CStateMachineBase::PerformStateTransition()
+ {
+ if (!IsActive())
+ {
+ iTransitionState = ETransitionExit;
+ DoStateTransitionStage();
+ }
+ }
+
+
+/** Do one stage of the state transition.
+This employs a self-completion mechanism to perform one stage of
+a state transition. The state machine object is set active and then its
+own status is completed, which results in its RunL being called.
+*/
+void CStateMachineBase::DoStateTransitionStage()
+ {
+ TRequestStatus* localStatus = &iStatus;
+ iStatus = KRequestPending;
+ SetActive();
+ User::RequestComplete(localStatus, KErrNone);
+ }
+
+
+/** Indicates if state machine is cancelling
+@return TBool ETrue if machine is cancelling
+*/
+TBool CStateMachineBase::Cancelling() const
+ {
+ return (EStateCancelling == iProtocolState) ? ETrue : EFalse;
+ }
+
+
+/** Indicates if state machine is to be cancelled
+@return TBool ETrue if machine is to be cancelled
+*/
+TBool CStateMachineBase::CancelPending() const
+ {
+ return iIsCancelPending;
+ }
+
+
+/** Cancel state machine
+@param aCancelSource The source that decided to cancel.
+*/
+void CStateMachineBase::CancelMachine(const TCancelSource& aCancelSource)
+ {
+ iIsCancelPending = ETrue;
+ iCancelSource = aCancelSource;
+
+ // Cancel the active procedure
+ CancelProcedure();
+
+ // Perform state transition
+ if (!IsActive() && (ETransitionNull == iTransitionState))
+ {
+ PerformStateTransition();
+ }
+ }
+
+
+/** Sets state machine attributes to represent cancelling
+*/
+void CStateMachineBase::SetMachineAsCancelling()
+ {
+ LBSLOG(ELogP2, "CStateMachineBase::SetMachineAsCancelling() protocol state ---> EStateCancelling \n");
+ iIsCancelPending = EFalse;
+ iProtocolState = CStateMachineBase::EStateCancelling;
+ }
+
+
+/** Cancel state machine
+@param aCancelSource The source that decided to cancel.
+@param aReason The reason for the cancellation.
+*/
+void CStateMachineBase::CancelMachine(const TCancelSource& aCancelSource,
+ TInt aReason)
+ {
+ // Store the specific cancel reason
+ switch (aCancelSource)
+ {
+ case ECancelNetworkCancel:
+ case ECancelNetworkError:
+ case ECancelNetworkTimeout:
+ iNetworkCancelReason = aReason;
+ break;
+
+ case ECancelClientTimeout:
+ case ECancelClientCancel:
+ case ECancelClientCancelSilent:
+ iClientCancelReason = aReason;
+ break;
+
+ case ECancelNone:
+ case ECancelClosing:
+ break;
+
+ default:
+ User::Panic(KProtocolModulePanic, EProtocolModuleCancelSource);
+ break;
+ };
+
+ // Cancel the machine
+ CancelMachine(aCancelSource);
+ }
+
+
+/** Set state machine as queued.
+This is called by individual derived state machines when they need
+to enter into a queued state.
+*/
+void CStateMachineBase::SetMachineAsQueued()
+ {
+ iIsMachineQueued = ETrue;
+ }
+
+
+/** Set state machine as queued.
+This is called by individual derived state machines when they need
+to enter into a queued state.
+*/
+TBool CStateMachineBase::IsMachineQueued() const
+ {
+ return iIsMachineQueued;
+ }
+
+
+/** Check for a queued request.
+Determine if there is a queued request and, if so, handle it.
+*/
+void CStateMachineBase::CheckForQueuedRequest()
+ {
+ // Check for a pending request
+ if (!IsActive() && iQueue->IsRequestPending())
+ {
+ // Perform the required action
+ DoQueuedRequest(iQueue->PopRequest());
+ }
+ }
+
+
+/** Active object completion handler
+*/
+void CStateMachineBase::RunL()
+ {
+ // Check we have completed ok
+ if (KErrNone == iStatus.Int())
+ {
+ // Which stage of the transition is this?
+ switch (iTransitionState)
+ {
+
+ // About to exit from a state
+ case ETransitionExit:
+ // Prepare state machine prior to the transition.
+ PreStateTransition();
+
+ // Exit current state.
+ ExitCurrentState();
+
+ // Do transition to next stage
+ iTransitionState = ETransitionEnter;
+ DoStateTransitionStage();
+ break;
+
+ // About to enter a state
+ case ETransitionEnter:
+ // Reset transition state value
+ iTransitionState = ETransitionNull;
+
+ // Perform state machine transition.
+ StateTransition();
+
+ // Enter new state.
+ EnterNewState();
+
+ // If an assistance data action is required then do it now.
+ // Note: Deferred until first measurement & control is handled.
+ if (iAssistanceDataActionRequired)
+ {
+ iAssistanceDataActionRequired = EFalse;
+ iObserver.DoAssistanceDataActions();
+ }
+
+ // Perform state machine post-transition actions
+ // Note: This may initiate another state transition
+ PostStateTransition();
+
+ // If the state machine is not active then we can see if there
+ // are any queued requests to be handled
+ if (!IsActive())
+ {
+ CheckForQueuedRequest();
+ }
+ break;
+
+ // Not changing state just performing asynchronous activities
+ case ETransitionNull:
+ default:
+ // If an assistance data action is required then do it now.
+ if (iAssistanceDataActionRequired)
+ {
+ iAssistanceDataActionRequired = EFalse;
+ iObserver.DoAssistanceDataActions();
+ }
+ break;
+ };
+
+ }
+
+ }
+
+
+/** Active object cancellation handler
+*/
+void CStateMachineBase::DoCancel()
+ {
+ iStatus = KErrCancel;
+ }
+
+
+/** Handle Network Measurement Control indication
+A measurement control indication has been received and the associated content
+must be stored. Note: At this stage the assistance data has already been handled
+by the protocol manager and is thus not passed into this method.
+
+@param aPosInfo The network reference location
+@param aQuality The location request quality
+@param aMethod Positioning method to adopt
+*/
+void CStateMachineBase::MeasurementControlInd(const TPositionInfoBase& aPosInfo,
+ const TLbsNetPosRequestQuality& aQuality,
+ const TLbsNetPosRequestMethod& aPosMethod)
+ {
+ // Ensure assistance data action is performed when appropriate
+ iAssistanceDataActionRequired = ETrue;
+
+ // Store ref location and location request criteria
+ StoreRefLoc(aPosInfo);
+ StoreLocReqQuality(aQuality);
+ StorePosMethod(aPosMethod);
+
+ iIsLocReqReceived = ETrue;
+ iIsMeasureControlHandled = EFalse;
+ }
+
+
+/** Handle LBS request for additional Assistance Data
+This is called by the protocol manager during an active procedure when
+a request has been made by LBS for further assistance data.
+*/
+void CStateMachineBase::AssistanceDataReq()
+ {
+ // Ensure assistance data action is performed when appropriate
+ iAssistanceDataActionRequired = ETrue;
+ iIsAdditionalDataExpected = ETrue;
+
+ // If not already active then we must get the state machine to
+ // perform asynchronous assistance data actions
+ if (!IsActive())
+ {
+ DoStateTransitionStage();
+ }
+ }
+
+
+/** Handle Network Additional Assistance data indication
+This is called by the protocol manager during an active procedure when
+an additional assistance data response is received from the network.
+*/
+void CStateMachineBase::AdditionalAssistDataInd()
+ {
+ // Stop the related timer
+ iAssistDataTimer->Cancel();
+
+ // Ensure assistance data action is performed when appropriate
+ iAssistanceDataActionRequired = ETrue;
+ iIsAdditionalDataExpected = EFalse;
+
+ // If not already active then we must get the state machine to
+ // perform asynchronous assistance data actions
+ if (!IsActive())
+ {
+ DoStateTransitionStage();
+ }
+ }
+
+
+/** Handle Network Measurement Control Error indication
+This is called by the protocol manager during an active procedure when
+a measurement control error is received from the network.
+@param aCancelRequired Indicates if the derived state machine requires
+ the state machine to be cancelled as a result of this error.
+*/
+void CStateMachineBase::HandleMeasureControlError(
+ const TBool& aCancelRequired, TInt aReason)
+ {
+ // Stop the related timer
+ iAssistDataTimer->Cancel();
+
+ // Ensure assistance data action is performed
+ iAssistanceDataActionRequired = ETrue;
+
+ // Do we have to cancel the state machine?
+ if (aCancelRequired)
+ {
+ iIsMeasureControlHandled = ETrue;
+ CancelMachine(ECancelNetworkCancel, aReason);
+ }
+ else
+ {
+ // If not already active then we must get the state machine to
+ // perform asynchronous assistance data actions
+ if (!IsActive())
+ {
+ DoStateTransitionStage();
+ }
+ }
+ }
+
+
+/** Network Measurement Control Error indication
+This implements the default actions to be taken if a derived class
+does not override this method.
+@param aReason The reason for network error
+*/
+void CStateMachineBase::MeasurementControlErrorInd(TInt aReason)
+ {
+ HandleMeasureControlError(EFalse, aReason);
+ }
+
+
+/** Handle a network error indication.
+*/
+void CStateMachineBase::NetworkErrorInd()
+ {
+ // Only handle this the first time
+ if (ECancelNetworkError != iCancelSource)
+ {
+ // Ensure assistance data actions are performed
+ if (iIsAdditionalDataExpected)
+ {
+ iAssistanceDataActionRequired = ETrue;
+ iIsAdditionalDataExpected = EFalse;
+ }
+ // Cancel state machine
+ CancelMachine(ECancelNetworkError);
+ }
+ }
+
+
+//-----------------------------------------------------------------------------
+// State Machine Request Queue Class
+//-----------------------------------------------------------------------------
+
+/** Static constructor
+@param aMaxEntries Maximum requests to be held in the queue.
+@return A new instance of the CStateQueue class.
+*/
+CStateQueue* CStateQueue::NewL(TInt aMaxEntries)
+ {
+ CStateQueue* self = new (ELeave) CStateQueue(aMaxEntries);
+ CleanupStack::PushL(self);
+ self->ConstructL(aMaxEntries);
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+
+/** Default private constructor
+@param aMaxEntries Maximum requests to be held in the queue.
+*/
+CStateQueue::CStateQueue(TInt aMaxEntries)
+ : iMaxEntries(aMaxEntries)
+ {
+ }
+
+
+/** Destructor
+*/
+CStateQueue::~CStateQueue()
+ {
+ iQueue.Reset();
+ }
+
+
+/** Private second stage constructor
+@param aMaxEntries Maximum requests to be held in the queue.
+*/
+void CStateQueue::ConstructL(TInt aMaxEntries)
+ {
+ iQueue.ReserveL(aMaxEntries);
+ }
+
+
+/** Check if there is a pending request
+@return TBool ETrue if there is a pending request in the queue
+*/
+TBool CStateQueue::IsRequestPending()
+ {
+ return (0 < iQueue.Count()) ? ETrue : EFalse;
+ }
+
+
+/** Add a request to the queue
+The new request is inserted at the start of the internal array
+because this makes it easier to pop the oldest request out of
+the array, @see CStateQueue::PopRequest()
+@param aNewRequest A number identifying the request to be queued.
+@return TInt KErrNone if there is no error queueing the request.
+*/
+TInt CStateQueue::AddRequest(TInt aNewRequest)
+ {
+ TInt err = KErrOverflow;
+ if (iMaxEntries > iQueue.Count())
+ {
+ TRAP(err, iQueue.InsertL(aNewRequest, 0));
+ }
+
+ return err;
+ }
+
+
+/** Pop the oldest request off the queue
+The entry at the end of the array represents the oldest queued request.
+@return TInt The number identifying the popped request
+*/
+TInt CStateQueue::PopRequest()
+ {
+ TInt request = 0;
+ if (0 < iQueue.Count())
+ {
+ request = iQueue[iQueue.Count() - 1];
+ iQueue.Remove(iQueue.Count() - 1);
+ }
+
+ return request;
+ }
+