bool Monster::saveTidy(PropertyBag &xml, PropertyBag &dataFile) const { saveTag(xml, dataFile, "preferredSpell", preferredSpell); StateMachine *fsm = GetStateMachine(); string type = "none"; if(fsm != 0) { type = fsm->getTypeString(); } saveTag(xml, dataFile, "fsm", type); return Creature::saveTidy(xml, dataFile); }
bool StateMachine::setSlotStateMachines(const PairStream* const msg) { // First remove the old list; and make sure we tell the old stMachList // that we're no longer their container. if (stMachList != nullptr) { List::Item* item = stMachList->getFirstItem(); while (item != nullptr) { Pair* p = static_cast<Pair*>(item->getValue()); Component* q = static_cast<Component*>(p->object()); q->container(nullptr); item = item->getNext(); } stMachList = nullptr; } // Build a new list containing only StateMachine class (or derived) objects if (msg != nullptr) { PairStream* newList = new PairStream(); // For each object in the list; if it's a StateMachine (or derived from) then // clone the object and add it to the new list. const List::Item* item = msg->getFirstItem(); while (item != nullptr) { const Pair* p = static_cast<const Pair*>(item->getValue()); const StateMachine* q = dynamic_cast<const StateMachine*>(p->object()); if (q != nullptr) { Pair* cp = static_cast<Pair*>(p->clone()); StateMachine* cq = static_cast<StateMachine*>(cp->object()); cq->container(this); newList->put(cp); } else { std::cerr << "StateMachine::setSlotStateMachines(): " << *p->slot() << " is not a StateMachine!" << std::endl; } item = item->getNext(); } // Set the pointer to the new stMach list stMachList = newList; } return true; }
void StateMachineTest::test() { enum class State: std::uint8_t { Start, End }; enum class Input: std::uint8_t { KeyA, KeyB }; typedef Interconnect::StateMachine<2, 2, State, Input> StateMachine; StateMachine m; m.addTransitions({ {State::Start, Input::KeyA, State::End}, {State::End, Input::KeyB, State::Start} }); std::ostringstream out; Debug::setOutput(&out); Interconnect::connect(m, &StateMachine::entered<State::Start>, [](State s) { Debug() << "start entered, previous" << std::uint8_t(s); }); Interconnect::connect(m, &StateMachine::exited<State::Start>, [](State s) { Debug() << "start exited, next" << std::uint8_t(s); }); Interconnect::connect(m, &StateMachine::entered<State::End>, [](State s) { Debug() << "end entered, previous" << std::uint8_t(s); }); Interconnect::connect(m, &StateMachine::exited<State::End>, [](State s) { Debug() << "end exited, next" << std::uint8_t(s); }); Interconnect::connect(m, &StateMachine::stepped<State::End, State::Start>, []() { Debug() << "going from end to start"; }); Interconnect::connect(m, &StateMachine::stepped<State::Start, State::End>, []() { Debug() << "going from start to end"; }); m.step(Input::KeyA) .step(Input::KeyB); CORRADE_COMPARE(out.str(), "start exited, next 1\n" "going from start to end\n" "end entered, previous 0\n" "end exited, next 0\n" "going from end to start\n" "start entered, previous 1\n"); }
void printTexTable(const StateMachine& sm, ostream& out) { const Transition* trans_ptr; int stateIndex, eventIndex; string actions; string nextState; out << "%& latex" << endl; out << "\\documentclass[12pt]{article}" << endl; out << "\\usepackage{graphics}" << endl; out << "\\begin{document}" << endl; // out << "{\\large" << endl; out << "\\begin{tabular}{|l||"; for(eventIndex=0; eventIndex < sm.numEvents(); eventIndex++) { out << "l"; } out << "|} \\hline" << endl; for(eventIndex=0; eventIndex < sm.numEvents(); eventIndex++) { out << " & \\rotatebox{90}{"; out << sm.getEvent(eventIndex).getShorthand(); out << "}"; } out << "\\\\ \\hline \\hline" << endl; for(stateIndex=0; stateIndex < sm.numStates(); stateIndex++) { out << sm.getState(stateIndex).getShorthand(); for(eventIndex=0; eventIndex < sm.numEvents(); eventIndex++) { out << " & "; trans_ptr = sm.getTransPtr(stateIndex, eventIndex); if (trans_ptr == NULL) { } else { actions = trans_ptr->getActionShorthands(); // FIXME: should compare index, not the string if (trans_ptr->getNextStateShorthand() != sm.getState(stateIndex).getShorthand() ) { nextState = trans_ptr->getNextStateShorthand(); } else { nextState = ""; } out << actions; if ((nextState.length() != 0) && (actions.length() != 0)) { out << "/"; } out << nextState; } } out << "\\\\" << endl; } out << "\\hline" << endl; out << "\\end{tabular}" << endl; // out << "}" << endl; out << "\\end{document}" << endl; }
EasyCamera(): cameraFeedState() { AxisCamera &camera = AxisCamera::GetInstance(); camera.WriteResolution(AxisCamera::kResolution_320x240); camera.WriteCompression(0); camera.WriteBrightness(0); cameraFeedState.RegisterState(SUBMIT_FRAME, 1); }
int main() { // Makes sure ResourceManager initializes before everything else. ResourceManager& resourceManager = ResourceManager::getInstance(); resourceManager.init(); // Run the stateMachine StateMachine stateMachine; stateMachine.run(); // Wait for the console window to be closed. std::cout << "\n\n"; LOGC("You can close the program when you have read the log above :)\nBe patient for this window to close"); while (true) { Sleep(100); } return EXIT_SUCCESS; }
bool Tower::initWithType(TowerType type, ControllerType controller) { if (BaseGameEntity::initWithControllerType(controller)) { // Architecture //------------------- m_pArchitecture = Architecture::getArchitectureForType(type); // Set Sprite //------------------- CCSpriteFrame *frame = CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(m_pArchitecture->getSpriteName()); m_pSprite->setDisplayFrame(frame); GameModel::instance()->getBatch()->addChild(m_pSprite); // Shooting Component //------------------- m_pComponents->setObject(ShootingComponent::create(this), kShootingComponent); // Touch Component //------------------- m_pComponents->setObject(TouchComponent::create(this, 1, this, menu_selector(Tower::popMenu), m_pArchitecture->getBodyRadius()), kTouchComponent); // State Machine Component //------------------- StateMachine<Tower> *pSM = StateMachine<Tower>::create(this); pSM->setGlobalState(TowerGlobalState::instance()); pSM->changeState(TowerStateIdle::instance()); m_pComponents->setObject(pSM, kStateMachineComponent); // Collision Component //------------------- getCollisionComponent()->setQueryRadius(m_pArchitecture->getGuardingRadius()); getCollisionComponent()->setCollisionRadius(m_pArchitecture->getGuardingRadius()); // Set entity type //------------------- m_eEntityType = kTower; return true; } return false; }
void StateMachineTest::testParentChildRelationship() { StateMachine machine; State s1(&machine); Transition t1(&s1); State s11(&s1); Transition t11(&s11); QCOMPARE(machine.childStates(), QList<State*>() << &s1); QVERIFY(machine.transitions().isEmpty()); QCOMPARE(s1.machine(), &machine); QCOMPARE(s1.childStates(), QList<State*>() << &s11); QCOMPARE(s1.transitions(), QList<Transition*>() << &t1); QCOMPARE(t1.sourceState(), &s1); QCOMPARE(s11.machine(), &machine); QVERIFY(s11.childStates().isEmpty()); QCOMPARE(s11.transitions(), QList<Transition*>() << &t11); QCOMPARE(t11.sourceState(), &s11); }
GEP_UNITTEST_TEST(StateMachine, INSERT_TEST_NAME_HERE) { GEP_UNITTEST_SETUP_EVENT_GLOBALS; auto& logging = TestLogging::instance(); //DummyLogging::instance(); // set up update framework _updateFramework.setElapsedTime(10.0f); // Add at least one callback so we know that we are still updating size_t frameCount = 0; _updateFramework.registerUpdateCallback([&](float){ logging.logWarning("frame %u:", frameCount); }); StateMachineFactory factory(&g_stdAllocator); StateMachine* pMainFsm = nullptr; // Test data. /// TODO Insert test data here /////////////////////////////////////////// // Actual tests. Don't put test data in here that has to be referenced // by the state machines, as they will get out of scope when pMainFsm // is actually run. { pMainFsm = factory.create("fsm"); /// TODO Insert test code here /////////////////////////////////////////// } pMainFsm->setLogging(&logging); // Run the machine pMainFsm->run(_updateFramework); for(frameCount = 0; frameCount < 20; ++frameCount) { _updateFramework.run(); } }
//============================================================================== StateMachine* Controller::_createStandingStateMachine() { using namespace dart::math::suffixes; StateMachine* standing = new StateMachine("standing"); State* standingState0 = new State(mAtlasRobot, "0"); TerminalCondition* tcStanding0 = new TimerCondition(standingState0, 0.3); standingState0->setTerminalCondition(tcStanding0); standingState0->setNextState(standingState0); standingState0->setDesiredJointPosition( "back_bky", 15.00_deg); // angle b/w pelvis and torso standingState0->setDesiredJointPosition("l_leg_hpy", -10.00_deg); standingState0->setDesiredJointPosition("r_leg_hpy", -10.00_deg); standingState0->setDesiredJointPosition("l_leg_kny", 30.00_deg); // left knee standingState0->setDesiredJointPosition("r_leg_kny", 30.00_deg); // right knee standingState0->setDesiredJointPosition( "l_leg_aky", -16.80_deg); // left ankle standingState0->setDesiredJointPosition( "r_leg_aky", -16.80_deg); // right ankle standingState0->setDesiredJointPosition( "l_arm_shx", -90.0_deg); // right ankle standingState0->setDesiredJointPosition( "r_arm_shx", +90.0_deg); // right ankle standing->addState(standingState0); standing->setInitialState(standingState0); return standing; }
void StateMachineHelper::updateDesinfectionSequence(int sequenceId, boolean update) { if (!update) { return; } switch (sequenceId) { case 0: // desinfection { digitalWrite(ProgramConstants::_flushingLight, LOW); digitalWrite(ProgramConstants::_desinfectionLight, HIGH); printToFirstLine("Program: desinf."); printToSecondLine("running"); break; } case 1: // ending desinfection - manually select end { _desinfectionLight = state.blinkLigth(_desinfectionLight, ProgramConstants::_desinfectionLight); break; } case StateMachine::_manullyToNextSequence: { printToSecondLine("press enter"); // overrwrite this function to allow manually move to next sequence _allowNewProgramSelection = true; _waitForManuallTrigger = true; break; } case StateMachine::_cycleEnd: { _stopEverything = true; // machine is prepared to be switched off when desinfection process ends //printToFirstLine("Desinf. end"); printToSecondLine("completed"); break; } default: { printToSecondLine("Error: Desinf."); digitalWrite(ProgramConstants::_errorLight, HIGH); delay(20000); break; } } }
void setup() { Serial.begin(9600); lcd.begin(16, 2); led.on(); machine.add_transition(0, 1, &button_pressed); machine.add_transition(1, 2, &one2two); machine.add_transition(2, 0, &button_pressed); machine.add_state_function(0, &hello); machine.add_state_function(1, &off); machine.add_state_function(2, &counting); }
int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QString inputMachineFile; QString outputSequenceFile; if (argc < 2){ inputMachineFile = "machine.txt"; } else{ inputMachineFile = a.arguments().at(1); } if (argc < 3){ outputSequenceFile = "sequence.txt"; } else{ outputSequenceFile = a.arguments().at(2); } StateMachine stateMachine; stateMachine.loadFromFile(inputMachineFile); qDebug() << "Printing all transitions"; stateMachine.printTransitions(); qDebug() << "Printing all inputs"; stateMachine.printInputs(); qDebug() << "Printing all outputs"; stateMachine.printOutput(); qDebug() << "Printing all states"; stateMachine.printStates(); qDebug() << "Generating test sequence"; QList<InputOutput> testSequence = stateMachine.getTestSequence(); qDebug() << "Writing to file"; stateMachine.writeInputSequenceToFile(testSequence,outputSequenceFile); return 0; }
void TestTable(FILE *fp) { fprintf(stderr, "Testing STT table.\n"); fseek(fp, 0, SEEK_SET); int Value; UTF32 nextcode = ReadCodePoint(fp); UTF32 i; for (i = 0; i <= UNI_MAX_LEGAL_UTF32; i++) { bool bMember; if (i == nextcode) { bMember = true; if (UNI_EOF != nextcode) { nextcode = ReadCodePoint(fp); if (nextcode <= i) { fprintf(stderr, "Codes in file are not in order (U+%04X).\n", static_cast<unsigned int>(nextcode)); exit(0); } } } else { bMember = false; } UTF32 Source[2]; Source[0] = i; Source[1] = L'\0'; const UTF32 *pSource = Source; UTF8 Target[5]; UTF8 *pTarget = Target; ConversionResult cr; cr = ConvertUTF32toUTF8(&pSource, pSource+1, &pTarget, pTarget+sizeof(Target)-1, lenientConversion); if (conversionOK == cr) { sm.TestString(Target, pTarget, bMember); } } }
void StateMachineHelper::checkCycleStatus() { int returnedSequenceId = state.checkProgramCycleProgress(_runningCycleId, _runningCycleSequenceId); if (returnedSequenceId == StateMachine::_manullyToNextSequence) { _waitForManuallTrigger = true; } boolean update = returnedSequenceId != _runningCycleSequenceId; if (returnedSequenceId != _runningCycleSequenceId) { // update current running cycle sequence _runningCycleSequenceId = returnedSequenceId; } switch (_runningCycleId) { case 1: // start-up and stand alone wash cycle //case 7: // stand alone wash cycle { updateStartUpSequence(returnedSequenceId, update); break; } case 2: // program 1 cycle case 3: // program 2 cycle case 4: // program 3 cycle { updateProgramSequence(returnedSequenceId); break; } case 5: { // after program 1, 2 or 3 updateWashSequence(returnedSequenceId, update); break; } case 6: { update = update ? update : returnedSequenceId == 1; updateDesinfectionSequence(returnedSequenceId, update); break; } } }
virtual void SetUp() { LOGUSRMOCK = new MockLogger; /* State Machine in Unknown state. */ state_machine_unknown.start(); /* State Machine in Missing state. */ state_machine_missing.start(); ON_CALL(hw_status, read_status()) .WillByDefault(Return(ModuleStatus::Status::NOT_PRESENT)); ON_CALL(sw_status, read_status()) .WillByDefault(Return(ModuleStatus::Status::NOT_PRESENT)); state_machine_missing.set_next_state(&hw_status, &sw_status); /* State Machine in Up state. */ state_machine_up.start(); ON_CALL(hw_status, read_status()) .WillByDefault(Return(ModuleStatus::Status::PRESENT)); ON_CALL(sw_status, read_status()) .WillByDefault(Return(ModuleStatus::Status::PRESENT)); state_machine_up.set_next_state(&hw_status, &sw_status); /* State Machine in Down state. */ state_machine_down.start(); ON_CALL(hw_status, read_status()) .WillByDefault(Return(ModuleStatus::Status::PRESENT)); ON_CALL(sw_status, read_status()) .WillByDefault(Return(ModuleStatus::Status::NOT_PRESENT)); state_machine_down.set_next_state(&hw_status, &sw_status); }
TEST(StateMachine, ramp_up) { StateMachine sm; // keep below minChannelLoad at first: relaxed sm.update(ChannelLoad(30, 100)); // smoothed: 0.15 sm.update(ChannelLoad(17, 100)); // smoothed: 0.16 EXPECT_STREQ("Relaxed", sm.state().name()); // now exceed minChannelLoad for 10 samples: active 1 sm.update(ChannelLoad(29, 100)); // smoothed: 0.225 for (unsigned i = 0; i < 8; ++i) { sm.update(ChannelLoad(20, 100)); EXPECT_STREQ("Relaxed", sm.state().name()); } sm.update(ChannelLoad(20, 100)); // smoothed: > 0.20 EXPECT_STREQ("Active 1", sm.state().name()); // now let's jump to active 3 directly sm.update(ChannelLoad(54, 100)); // smoothed: 0.37 EXPECT_STREQ("Active 3", sm.state().name()); // go to restrictive state (over active 5) sm.update(ChannelLoad(83, 100)); // smoothed: 0.60 EXPECT_STREQ("Active 5", sm.state().name()); for (unsigned i = 0; i < 8; ++i) { sm.update(ChannelLoad(60, 100)); EXPECT_STREQ("Active 5", sm.state().name()); } sm.update(ChannelLoad(60, 100)); EXPECT_STREQ("Restrictive", sm.state().name()); }
void MyOwner::UpdateStateMachine() { mStateMachine.ProcessStateTransitions(); mStateMachine.UpdateStates(); }
unsigned long StateMachineHelper::blinkLigth(unsigned long milliSecs, int pin) { return state.blinkLigth(milliSecs, pin); }
void StateMachineHelper::updateProgramSequence(int sequenceId) { switch (sequenceId) { case StateMachine::_displayRunningCycle: { printToSecondLine("running"); switchAllProgramLights(LOW); digitalWrite(ProgramConstants::_flushingLight, LOW); if (_lastRunningProgram == 1) { printToFirstLine("Program: 1"); digitalWrite(ProgramConstants::_program1Light, HIGH); } else if (_lastRunningProgram == 2) { printToFirstLine("Program: 2"); digitalWrite(ProgramConstants::_program2Light, HIGH); } else if (_lastRunningProgram = 3) { printToFirstLine("Program: 3"); digitalWrite(ProgramConstants::_program3Light, HIGH); } break; } case 0: // program is running { boolean interrupt = state.hasInterruption(); // to prevent instant refresh if (_lastState == interrupt) { return; } else { _lastState = interrupt; } if (interrupt) { printToSecondLine("pre-cleaning"); } else { printToSecondLine("running"); } break; } case StateMachine::_cycleEnd: { switchAllProgramLights(LOW); processProgramEnd(); break; } default: { printToSecondLine("Error: Init"); digitalWrite(ProgramConstants::_errorLight, HIGH); delay(20000); break; } } }
void changeState(Enemy::States newState) { mStateMachine.changeState(mStates.at(newState).get(), newState); }
unsigned int getCurrentStateType() { return mStateMachine.getCurrentStateType(); }
void print_controller_C(ostream& out, string component, const StateMachine& machine) { out << "// Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<< endl; out << "// " << machine.getIdent() << ": " << machine.getShorthand() << endl; out << endl; out << "#include \"Global.h\"" << endl; out << "#include \"slicc_util.h\"" << endl; out << "#include \"" << component << "_Controller.h\"" << endl; out << "#include \"" << component << "_State.h\"" << endl; out << "#include \"" << component << "_Event.h\"" << endl; out << "#include \"Types.h\"" << endl; out << "#include \"Profiler.h\"" << endl; out << "#include \"Network.h\"" << endl; out << endl; out << "// static profiler defn" << endl; out << component << "_Profiler " << component << "_Controller::s_profiler;" << endl; out << endl; out << "// constructor" << endl; out << component << "_Controller::" << component << "_Controller(NodeID id, Network* network_ptr)" << endl; out << "{" << endl; out << " m_id = id;" << endl; // Initialize member variables const Vector<Symbol*>& symbols = g_sym_table.getAllSymbols(); for (int i=0; i < symbols.size(); i++) { Var* var = dynamic_cast<Var*>(symbols[i]); if (var == NULL || var->getMachine() != &machine) { continue; } out << " // " << var->cIdent() << endl; if (var->existPair("network")) { // Network port object string network = var->lookupPair("network"); string ordered = var->lookupPair("ordered"); string vnet = var->lookupPair("virtual_network"); out << " m_" << var->cIdent() << "_ptr = network_ptr->get" << network << "NetQueue(MachineType_" << var->getMachine()->getIdent() << ", m_id, " << ordered << ", " << vnet << ");\n"; } else if (var->getType()->existPair("primitive") || (dynamic_cast<Enum*>(var->getType()) != NULL)) { // Normal non-object out << " m_" << var->cIdent() << "_ptr = new " << var->getType()->cIdent() << ";\n"; } else { // Normal Object out << " m_" << var->cIdent() << "_ptr = new " << var->getType()->cIdent(); if (!var->getType()->existPair("non_obj")) { if (var->existPair("constructor_hack")) { string constructor_hack = var->lookupPair("constructor_hack"); out << "(m_id, " << constructor_hack << ")"; } else { out << "(m_id)"; } out << ";\n"; } } out << " assert(m_" << var->cIdent() << "_ptr != NULL);" << endl; // Set to the default value if (var->existPair("default")) { out << " (*m_" << var->cIdent() << "_ptr) = " << var->lookupPair("default") << "; // Object default" << endl; } else if (var->getType()->hasDefault()) { out << " (*m_" << var->cIdent() << "_ptr) = " << var->getType()->getDefault() << "; // Type " << var->getType()->getIdent() << " default" << endl; } // Set ordering if (var->existPair("ordered")) { // A buffer string ordered = var->lookupPair("ordered"); out << " m_" << var->cIdent() << "_ptr->setOrdering(" << ordered << ");\n"; } // Set randomization if (var->existPair("random")) { // A buffer string value = var->lookupPair("random"); out << " m_" << var->cIdent() << "_ptr->setRandomization(" << value << ");\n"; } out << endl; } // Set the queue consumers for(int i=0; i < machine.numInPorts(); i++) { out << " " << machine.getInPort(i).getCode() << ".setConsumer(this);" << endl; } out << endl; // Set the queue descriptions for(int i=0; i < machine.numInPorts(); i++) { out << " " << machine.getInPort(i).getCode() << ".setDescription(\"[Node \" + int_to_string(m_id) + \", " << component << ", " << machine.getInPort(i).toString() << "]\");" << endl; } // Initialize the transition profiling out << endl; for(int i=0; i<machine.numTransitions(); i++) { const Transition& t = machine.getTransition(i); const Vector<Action*>& action_vec = t.getActions(); int numActions = action_vec.size(); // Figure out if we stall bool stall = false; for (int i=0; i<numActions; i++) { if(action_vec[i]->getIdent() == "z_stall") { stall = true; } } // Only possible if it is not a 'z' case if (!stall) { out << " s_profiler.possibleTransition(" << component << "_State_" << t.getStatePtr()->getIdent() << ", " << component << "_Event_" << t.getEventPtr()->getIdent() << ");" << endl; } } out << "}" << endl; out << endl; { out << component << "_Controller::~" << component << "_Controller()" << endl; out << "{" << endl; const Vector<Symbol*>& symbols = g_sym_table.getAllSymbols(); for (int i=0; i < symbols.size(); i++) { Var* var_ptr = dynamic_cast<Var*>(symbols[i]); if (var_ptr == NULL || var_ptr->getMachine() != &machine) { continue; } if (!var_ptr->existPair("network")) { // Normal Object out << " delete m_" << var_ptr->cIdent() << "_ptr;\n"; } } out << "}" << endl; } { out << endl; out << "void " << component << "_Controller::printConfig(ostream& out)\n"; out << "{\n"; out << " out << heading(\"" << component << " Config\");\n"; const Vector<Symbol*>& symbols = g_sym_table.getAllSymbols(); for (int i=0; i < symbols.size(); i++) { Var* var_ptr = dynamic_cast<Var*>(symbols[i]); if (var_ptr == NULL || var_ptr->getMachine() != &machine) { continue; } if (!var_ptr->existPair("network") && (!var_ptr->getType()->existPair("primitive"))) { // Normal Object out << " m_" << var_ptr->cIdent() << "_ptr->printConfig(out);\n"; } } out << " out << endl;\n"; out << "}" << endl; } out << endl; out << "void " << component << "_Controller::print(ostream& out) const { out << \"[" << component << "_Controller \" << m_id << \"]\"; }" << endl; out << endl; out << "// Actions" << endl; out << endl; for(int i=0; i < machine.numActions(); i++) { const Action& action = machine.getAction(i); if (action.existPair("c_code")) { out << "//" << action.getDescription() << endl; out << "void " << component << "_Controller::" << action.getIdent() << "(const Address& addr)" << endl; out << "{" << endl; out << " DEBUG_MSG(GENERATED_COMP, HighPrio,\"executing\");" << endl; out << action.lookupPair("c_code"); out << "}" << endl; } out << endl; } // Function definitions { const Vector<Symbol*>& symbols = g_sym_table.getAllSymbols(); for (int i=0; i < symbols.size(); i++) { Func* func_ptr = dynamic_cast<Func*>(symbols[i]); if (func_ptr == NULL || func_ptr->getMachine() != &machine) { continue; } string code; func_ptr->funcDefinition(code); out << code; } } }
GEP_UNITTEST_TEST(StateMachine, UpdateStepBehavior) { GEP_UNITTEST_SETUP_EVENT_GLOBALS; auto& logging = TestLogging::instance(); //DummyLogging::instance(); // set up update framework _updateFramework.setElapsedTime(10.0f); // Add at least one callback so we know that we are still updating size_t frameCount = 0; _updateFramework.registerUpdateCallback([&](float){ logging.logWarning("frame %u:", frameCount); }); StateMachineFactory factory(&g_stdAllocator); StateMachine* pMainFsm = nullptr; // Test data. size_t conditionCheckCount = 0; size_t updateCount = 0; // Actual tests. Don't put test data in here that has to be referenced // by the state machines, as they will get out of scope when pMainFsm // is actually run. { pMainFsm = factory.create("fsm"); pMainFsm->setLogging(&logging); auto pState_A = pMainFsm->create<State>("A"); auto pState_B = pMainFsm->create<State>("B"); auto pState_C = pMainFsm->create<State>("C"); pState_C->setLeaveCondition([](){ return true; }); // Adding state transitions pMainFsm->addTransition("__enter", "A"); pMainFsm->addTransition("A", "B", [&](){ // This should be hit conditionCheckCount++; return true; }); pMainFsm->addTransition("B", "C", [&](){ // This should not be hit conditionCheckCount++; return true; }); pMainFsm->addTransition("C", "__leave"); pState_B->getLeaveEvent()->registerListener([&](State::LeaveEventData* pData){ GEP_ASSERT(conditionCheckCount == 1, "Condition check 'A->B' not performed!"); conditionCheckCount = 0; pData->setNextState(pState_C); return gep::EventResult::Handled; }); pState_C->getLeaveEvent()->registerListener([&](State::LeaveEventData*){ GEP_ASSERT(conditionCheckCount == 0, "Condition check 'B->C' should not have been performed!"); conditionCheckCount = 0; return gep::EventResult::Handled; }); // Set update event listeners. They should use the UpdateStepBehavior options. ////////////////////////////////////////////////////////////////////////// pState_A->getUpdateEvent()->registerListener([&](State::UpdateEventData* pData){ pData->setUpdateStepBehavior(State::UpdateStepBehavior::Leave); updateCount++; return gep::EventResult::Handled; }); pState_B->getUpdateEvent()->registerListener([&](State::UpdateEventData* pData){ pData->setUpdateStepBehavior(State::UpdateStepBehavior::LeaveWithNoConditionChecks); return gep::EventResult::Handled; }); } pMainFsm->setLogging(&logging); // Run the machine pMainFsm->run(_updateFramework); for(frameCount = 0; frameCount < 5; ++frameCount) { _updateFramework.run(); } GEP_ASSERT(updateCount > 0, "State A should have at least be updated once!"); }
void print_C_switch(ostream& out, string component, const StateMachine& machine) { out << "// Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<< endl; out << "// " << machine.getIdent() << ": " << machine.getShorthand() << endl; out << endl; out << "#include \"Global.h\"" << endl; out << "#include \"" << component << "_Controller.h\"" << endl; out << "#include \"" << component << "_State.h\"" << endl; out << "#include \"" << component << "_Event.h\"" << endl; out << "#include \"Types.h\"" << endl; out << "#include \"System.h\"" << endl; out << "#include \"Profiler.h\"" << endl; out << endl; out << "#define HASH_FUN(state, event) ((int(state)*" << component << "_Event_NUM)+int(event))" << endl; out << endl; out << "TransitionResult " << component << "_Controller::doTransition(" << component << "_Event event, " << component << "_State state, " << "const Address& addr)" << endl; out << "{" << endl; out << " " << component << "_State next_state = state;" << endl; out << endl; out << " DEBUG_NEWLINE(GENERATED_COMP, MedPrio);" << endl; out << " DEBUG_MSG(GENERATED_COMP, MedPrio,*this);" << endl; out << " DEBUG_EXPR(GENERATED_COMP, MedPrio,g_eventQueue_ptr->getTime());" << endl; out << " DEBUG_EXPR(GENERATED_COMP, MedPrio,state);" << endl; out << " DEBUG_EXPR(GENERATED_COMP, MedPrio,event);" << endl; out << " DEBUG_EXPR(GENERATED_COMP, MedPrio,addr);" << endl; out << endl; out << " TransitionResult result = doTransitionWorker(event, state, next_state, addr);" << endl; out << endl; out << " if (result == TransitionResult_Valid) {" << endl; out << " DEBUG_EXPR(GENERATED_COMP, MedPrio, next_state);" << endl; out << " DEBUG_NEWLINE(GENERATED_COMP, MedPrio);" << endl; out << " s_profiler.countTransition(state, event);" << endl; out << " if (g_param_ptr->PROTOCOL_DEBUG_TRACE()) {" << endl << " g_system_ptr->getProfiler()->profileTransition(\"" << component << "\", m_id, addr, " << endl << " " << component << "_State_to_string(state), " << endl << " " << component << "_Event_to_string(event), " << endl << " " << component << "_State_to_string(next_state), " << endl << " \"\");" << endl << " }" << endl; out << " " << component << "_setState(addr, next_state);" << endl; out << " " << endl; out << " } else if (result == TransitionResult_ResourceStall) {" << endl; out << " if (g_param_ptr->PROTOCOL_DEBUG_TRACE()) {" << endl << " g_system_ptr->getProfiler()->profileTransition(\"" << component << "\", m_id, addr, " << endl << " " << component << "_State_to_string(state), " << endl << " " << component << "_Event_to_string(event), " << endl << " " << component << "_State_to_string(next_state), " << endl << " \"Resource Stall\");" << endl << " }" << endl; out << " } else if (result == TransitionResult_ProtocolStall) {" << endl; out << " DEBUG_MSG(GENERATED_COMP,HighPrio,\"stalling\");" << endl << " DEBUG_NEWLINE(GENERATED_COMP, MedPrio);" << endl; out << " if (g_param_ptr->PROTOCOL_DEBUG_TRACE()) {" << endl << " g_system_ptr->getProfiler()->profileTransition(\"" << component << "\", m_id, addr, " << endl << " " << component << "_State_to_string(state), " << endl << " " << component << "_Event_to_string(event), " << endl << " " << component << "_State_to_string(next_state), " << endl << " \"Protocol Stall\");" << endl << " }" << endl << " }" << endl; out << " return result;" << endl; out << "}" << endl; out << endl; out << "TransitionResult " << component << "_Controller::doTransitionWorker(" << component << "_Event event, " << component << "_State state, " << component << "_State& next_state, " << "const Address& addr)" << endl; out << "{" << endl; out << "" << endl; out << " switch(HASH_FUN(state, event)) {" << endl; Map<string, Vector<string> > code_map; // This map will allow suppress generating duplicate code Vector<string> code_vec; for(int i=0; i<machine.numTransitions(); i++) { const Transition& t = machine.getTransition(i); string case_string = component + "_State_" + t.getStatePtr()->getIdent() + ", " + component + "_Event_" + t.getEventPtr()->getIdent(); string code; code += " {\n"; // Only set next_state if it changes if (t.getStatePtr() != t.getNextStatePtr()) { code += " next_state = " + component + "_State_" + t.getNextStatePtr()->getIdent() + ";\n"; } const Vector<Action*>& action_vec = t.getActions(); int numActions = action_vec.size(); // Check for resources Vector<string> code_sorter; const Map<Var*, int>& res = t.getResources(); Vector<Var*> res_keys = res.keys(); for (int i=0; i<res_keys.size(); i++) { string temp_code; temp_code += " if (!" + (res_keys[i]->getCode()) + ".areNSlotsAvailable(" + int_to_string(res.lookup(res_keys[i])) + ")) {\n"; temp_code += " return TransitionResult_ResourceStall;\n"; temp_code += " }\n"; code_sorter.insertAtBottom(temp_code); } // Emit the code sequences in a sorted order. This makes the // output deterministic (without this the output order can vary // since Map's keys() on a vector of pointers is not deterministic code_sorter.sortVector(); for (int i=0; i<code_sorter.size(); i++) { code += code_sorter[i]; } // Figure out if we stall bool stall = false; for (int i=0; i<numActions; i++) { if(action_vec[i]->getIdent() == "z_stall") { stall = true; } } if (stall) { code += " return TransitionResult_ProtocolStall;\n"; } else { for (int i=0; i<numActions; i++) { code += " " + action_vec[i]->getIdent() + "(addr);\n"; } code += " return TransitionResult_Valid;\n"; } code += " }\n"; // Look to see if this transition code is unique. if (code_map.exist(code)) { code_map.lookup(code).insertAtBottom(case_string); } else { Vector<string> vec; vec.insertAtBottom(case_string); code_map.add(code, vec); code_vec.insertAtBottom(code); } } // Walk through all of the unique code blocks and spit out the // corresponding case statement elements for (int i=0; i<code_vec.size(); i++) { string code = code_vec[i]; // Iterative over all the multiple transitions that share the same code for (int case_num=0; case_num<code_map.lookup(code).size(); case_num++) { string case_string = code_map.lookup(code)[case_num]; out << " case HASH_FUN(" << case_string << "):" << endl; } out << code; } out << " default:" << endl; out << " WARN_EXPR(m_id);" << endl; out << " WARN_EXPR(g_eventQueue_ptr->getTime());" << endl; out << " WARN_EXPR(addr);" << endl; out << " WARN_EXPR(event);" << endl; out << " WARN_EXPR(state);" << endl; out << " ERROR_MSG(\"Invalid transition\");" << endl; out << " }" << endl; out << " return TransitionResult_Valid;" << endl; out << "}" << endl; }
TEST(StateMachine, ramp_down) { StateMachine sm; // fill up CL ring buffer first and go to restrictive state for (unsigned i = 0; i < 100; ++i) { sm.update(ChannelLoad(70, 100)); } ASSERT_STREQ("Restrictive", sm.state().name()); // cool down to CL = 50% // ring buffer: 60.0, 55.0, 52.5, 51.25, 50.625... for (unsigned i = 0; i < 50; ++i) { sm.update(ChannelLoad(50, 100)); } EXPECT_STREQ("Restrictive", sm.state().name()); // ring buffer: 55.0, 52.5... -> active 5 sm.update(ChannelLoad(50, 100)); EXPECT_STREQ("Active 5", sm.state().name()); // ring buffer: 51.25, 50.625... -> active 5 sm.update(ChannelLoad(50, 100)); sm.update(ChannelLoad(50, 100)); EXPECT_STREQ("Active 5", sm.state().name()); // ring buffer: 50.625... -> active 4 sm.update(ChannelLoad(50, 100)); EXPECT_STREQ("Active 4", sm.state().name()); }
void print_controller_h(ostream& out, string component, const StateMachine& machine) { out << "// Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<< endl; out << "// " << machine.getIdent() << ": " << machine.getShorthand() << endl; out << endl; out << "#ifndef " << component << "_CONTROLLER_H" << endl; out << "#define " << component << "_CONTROLLER_H" << endl; out << endl; out << "#include \"Global.h\"" << endl; out << "#include \"Consumer.h\"" << endl; out << "#include \"TransitionResult.h\"" << endl; out << "#include \"Types.h\"" << endl; out << "#include \"Network.h\"" << endl; out << "#include \"" << component << "_Profiler.h\"" << endl; out << endl; out << "class " << component << "_Controller : public Consumer {" << endl; out << "public:" << endl; out << " " << component << "_Controller(NodeID id, Network* network_ptr);" << endl; out << " ~" << component << "_Controller();" << endl; out << " void print(ostream& out) const;" << endl; out << " void wakeup();" << endl; out << " void printConfig(ostream& out);" << endl; out << " static void dumpStats(ostream& out) { s_profiler.dumpStats(out); }" << endl; out << " static void clearStats() { s_profiler.clearStats(); }" << endl; // Member variables out << " // Member variables (should probably be private)" << endl; const Vector<Symbol*>& symbols = g_sym_table.getAllSymbols(); for (int i=0; i < symbols.size(); i++) { Var* var_ptr = dynamic_cast<Var*>(symbols[i]); if (var_ptr == NULL || var_ptr->getMachine() != &machine) { continue; } out << " " << var_ptr->getType()->cIdent() << "* m_" << var_ptr->cIdent() << "_ptr;" << endl; } out << "private:" << endl; out << " TransitionResult doTransition(" << component << "_Event event, " << component << "_State state, const Address& addr); // in " << component << "_Transitions.C" << endl; out << " TransitionResult doTransitionWorker(" << component << "_Event event, " << component << "_State state, " << component << "_State& next_state, const Address& addr); // in " << component << "_Transitions.C" << endl; out << " NodeID m_id;" << endl; out << " static " << component << "_Profiler s_profiler;" << endl; // internal function protypes { out << " // Internal functions" << endl; const Vector<Symbol*>& symbols = g_sym_table.getAllSymbols(); for (int i=0; i < symbols.size(); i++) { Func* func_ptr = dynamic_cast<Func*>(symbols[i]); if (func_ptr == NULL || func_ptr->getMachine() != &machine) { continue; } string proto; func_ptr->funcPrototype(proto); if (proto != "") { out << " " << proto; } } } out << " // Actions" << endl; for(int i=0; i < machine.numActions(); i++) { const Action& action = machine.getAction(i); out << " void " << action.getIdent() << "(const Address& addr);" << endl; } out << "};" << endl; out << "#endif // " << component << "_CONTROLLER_H" << endl; }
void print_profiler_C(ostream& out, string component, const StateMachine& machine) { out << "// Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<< endl; out << "// " << machine.getIdent() << ": " << machine.getShorthand() << endl; out << endl; out << "#include \"" << component << "_Profiler.h\"" << endl; out << endl; // Constructor out << component << "_Profiler::" << component << "_Profiler()" << endl; out << "{" << endl; out << " for (int state = 0; state < " << component << "_State_NUM; state++) {" << endl; out << " for (int event = 0; event < " << component << "_Event_NUM; event++) {" << endl; out << " m_possible[state][event] = false;" << endl; out << " m_counters[state][event] = 0;" << endl; out << " }" << endl; out << " }" << endl; out << "}" << endl; // Clearstats out << "void " << component << "_Profiler::clearStats()" << endl; out << "{" << endl; out << " for (int state = 0; state < " << component << "_State_NUM; state++) {" << endl; out << " for (int event = 0; event < " << component << "_Event_NUM; event++) {" << endl; out << " m_counters[state][event] = 0;" << endl; out << " }" << endl; out << " }" << endl; out << "}" << endl; // Count Transition out << "void " << component << "_Profiler::countTransition(" << component << "_State state, " << component << "_Event event)" << endl; out << "{" << endl; out << " assert(m_possible[state][event]);" << endl; out << " m_counters[state][event]++;" << endl; out << "}" << endl; // Possible Transition out << "void " << component << "_Profiler::possibleTransition(" << component << "_State state, " << component << "_Event event)" << endl; out << "{" << endl; out << " m_possible[state][event] = true;" << endl; out << "}" << endl; // dumpStats out << "void " << component << "_Profiler::dumpStats(ostream& out) const" << endl; out << "{" << endl; out << " out << \" --- " << component << " ---\" << endl;" << endl; out << " for (int state = 0; state < " << component << "_State_NUM; state++) {" << endl; out << " for (int event = 0; event < " << component << "_Event_NUM; event++) {" << endl; out << " if (m_possible[state][event]) {" << endl; out << " int count = m_counters[state][event];" << endl; out << " out << (" << component << "_State) state << \" \" << (" << component << "_Event) event << \" \" << count;" << endl; out << " if (count == 0) {" << endl; out << " out << \" <-- \";" << endl; out << " }" << endl; out << " out << endl;" << endl; out << " }" << endl; out << " }" << endl; out << " out << endl;" << endl; out << " }" << endl; out << "}" << endl; }
void Character::Update() { // Update state machine mStateMachine.ProcessStateTransitions(); mStateMachine.UpdateStates(); }
void loop() { int oldstate = machine.current_state(); int nustate = machine.loop(); }