Leaked source code of windows server 2003
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
//-----------------------------------------------------------------------------
//
//
// File: statemachinebase.cpp
//
// Description:
// Implementation of CStateMachineBaseClass
//
// Author: Mike Swafford (MikeSwa)
//
// History:
// 12/11/2000 - MikeSwa Created
//
// Copyright (C) 2000 Microsoft Corporation
//
//-----------------------------------------------------------------------------
#include "aqprecmp.h"
#include "statemachinebase.h"
//---[ CStateMachineBase::CStateMachineBase ]-----------------------
//
//
// Description:
// CStateMachineBase constructor
// Parameters:
// - dwInitialState Initial state to set state
// machine to
// dwStateMachineSignature Signature of the state machine
// subclass
// Returns:
// -
// History:
// 6/5/2000 - t-toddc Created
//
//------------------------------------------------------------------
CStateMachineBase::CStateMachineBase(DWORD dwInitialState, DWORD dwStateMachineSignature) : m_dwSignature(STATE_MACHINE_BASE_SIG), m_dwStateMachineSignature(dwStateMachineSignature), m_dwCurrentState(dwInitialState) { };
//---[ CStateMachineBase::dwGetCurrentState ]----------------------
//
//
// Description:
// returns the current state of the state machine
// Parameters:
// -
// Returns:
// - current state
// History:
// 6/5/2000 - t-toddc Created
//
//------------------------------------------------------------------
DWORD CStateMachineBase::dwGetCurrentState() { return m_dwCurrentState; }
//---[ CStateMachineBase::dwGetNextState ]-------------------------
//
//
// Description:
// sets the next state based on current state and input action.
// Uses InterlockedCompareExchange to make sure that the state
// transition is thread-safe.
// Parameters:
// - dwAction the current action causing the state transition
// Returns:
// - the resultant state based on the current state and
// input action
// History:
// 6/5/2000 - t-toddc Created
//
//------------------------------------------------------------------
DWORD CStateMachineBase::dwGetNextState(DWORD dwAction) { TraceFunctEnter("CStateMachineBase::dwGetNextState");
DWORD dwCurrentState; DWORD dwNextState;
do { dwCurrentState = m_dwCurrentState; dwNextState = dwCalcStateFromStateAndAction(dwCurrentState, dwAction); if (dwCurrentState == dwNextState) break; // no work to be done
} while (InterlockedCompareExchange((LPLONG) &m_dwCurrentState, (LONG) dwNextState, (LONG) dwCurrentState)!= (LONG) dwCurrentState); DebugTrace((LPARAM) this, "CStateMachineBase state transition: %X->%X", dwCurrentState, dwNextState); TraceFunctLeave(); return dwNextState; }
//---[ CStateMachineBase::dwCalcStateFromStateAndAction ]------------
//
//
// Description:
// iterates through the state transition table to find the
// next state associated with the current state and input action
// Parameters:
// - dwStartState start state for this transition
// dwAction the action associated with this transition
// Returns:
// - the resultant state associated with current state and action
// History:
// 6/5/2000 - t-toddc Created
//
//
//------------------------------------------------------------------
DWORD CStateMachineBase::dwCalcStateFromStateAndAction(DWORD dwStartState, DWORD dwAction) { TraceFunctEnter("CStateMachineBase::dwCalcStateFromStateAndAction"); // if the action is unknown to state table, return start state
DWORD dwNextState = dwStartState; DWORD i; const STATE_TRANSITION* pTransitionTable; DWORD dwNumTransitions; BOOL fFoundTransition = FALSE; // obtain the transition table
getTransitionTable(&pTransitionTable, &dwNumTransitions);
// find the new state
for(i=0; i < dwNumTransitions; i++) { if (pTransitionTable[i].dwCurrentState == dwStartState && pTransitionTable[i].dwAction == dwAction) { dwNextState = pTransitionTable[i].dwNextState; fFoundTransition = TRUE; break; } }
ASSERT(fFoundTransition && "action unknown to state table"); if (!fFoundTransition) DebugTrace((LPARAM) this,"action %X unknown to state tabe", dwAction);
TraceFunctLeave(); return dwNextState; }
//---[ CStateMachineBase::fValidateStateTable ]---------------------
//
//
// Description:
// loops through all transitions and checks that
// a) all possible states are start states
// b) for every state, every possible action yields another state
// Parameters:
// -
// Returns:
// - true/false if state table is valid/invalid
// History:
// 6/5/2000 - t-toddc Created
//
//------------------------------------------------------------------
BOOL CStateMachineBase::fValidateStateTable() { TraceFunctEnter("CStateMachineBase::fValidateStateTable");
DWORD i, j, k; // iterators
DWORD dwEndState; DWORD dwAction; DWORD dwCurrentState; BOOL fFoundEndStateAsStartState = false; BOOL fActionSupportedByEveryState = false; const STATE_TRANSITION* pTransitionTable; DWORD dwNumTransitions; BOOL fRetVal = false;
// obtain the transition table
getTransitionTable(&pTransitionTable, &dwNumTransitions);
for(i = 0; i < dwNumTransitions; i++) { // initialize booleans within loop
fFoundEndStateAsStartState = false; // grab the current action
dwAction = pTransitionTable[i].dwAction; // grab the current end state
dwEndState = pTransitionTable[i].dwNextState;
// loop over all transitions
for (j = 0; j < dwNumTransitions; j++) { // check that the current end state is a start state
if (pTransitionTable[j].dwCurrentState == dwEndState) { fFoundEndStateAsStartState = true; }
// check that every action is supported by every state
fActionSupportedByEveryState = false; dwCurrentState = pTransitionTable[j].dwCurrentState; // the current action might not be in this particular transition,
// but it must be in a transition with this dwCurrentState as the start state
if (pTransitionTable[j].dwAction != dwAction) { // loop over all transitions again to guarantee the above.
for(k = 0; k < dwNumTransitions; k++) { // there must exist a state transition with the current state
// from above and the given action
if (pTransitionTable[k].dwAction == dwAction && pTransitionTable[k].dwCurrentState == dwCurrentState) { fActionSupportedByEveryState = true; break; } } } else { fActionSupportedByEveryState = true; }
// bail on false if the current action is not supported by every state
ASSERT(fActionSupportedByEveryState && "Invalid state table: action not supported by every state"); if (!fActionSupportedByEveryState) { fRetVal = false; DebugTrace((LPARAM) this, "Invalid state table: action not supported by every state"); goto Cleanup; } // break out of inner loop if the current end state has been found
// as a start state
if (fFoundEndStateAsStartState) break; }
// bail on false if an end state is not also a start state
ASSERT(fFoundEndStateAsStartState && "Invalid state table: an end state is not also a start state"); if (!fFoundEndStateAsStartState) { fRetVal = false; DebugTrace((LPARAM) this, "Invalid state table: an end state is not also a start state"); goto Cleanup; } }
// if it makes it this far, it is undoubtedly valid.
fRetVal = true;
Cleanup: TraceFunctLeave(); return fRetVal; }
|