, :
#include <cassert>
#include <iostream>
#include <map>
class Machine;
typedef void (*StateFunctionPtr)(Machine& context);
void starting1(Machine& context) {std::cout << "S1 ";}
void final1(Machine& context) {std::cout << "F1 ";}
void starting2(Machine& context) {std::cout << "S2 ";}
void final2(Machine& context) {std::cout << "F2 ";}
void sendPayload(Machine& context) {std::cout << "SP ";}
void sendEnd(Machine& context) {std::cout << "SE ";}
void receivePayload(Machine& context) {std::cout << "RP ";}
void receiveEnd(Machine& context) {std::cout << "RE ";}
namespace State
{
enum Type {start, handshake1, handshake2, handshake3,
handshake4, xferPayload, endPayload};
};
struct StateKey
{
bool operator<(const StateKey& rhs) const
{
return
(state < rhs.state)
|| ( (state == rhs.state) && (isReceiving < rhs.isReceiving) )
|| ( (state == rhs.state) && (isReceiving == rhs.isReceiving)
&& (startsAt2 < rhs.startsAt2) );
}
bool startsAt2;
bool isReceiving;
State::Type state;
};
struct StateEffect
{
StateFunctionPtr function;
State::Type newState;
};
struct StatePair
{
StateKey key;
StateEffect effect;
};
const StatePair stateTable[] =
{
{{0, 0, State::start}, {&starting1, State::handshake1}},
{{0, 0, State::handshake1}, {&final1, State::handshake2}},
{{0, 0, State::handshake2}, {&starting2, State::handshake3}},
{{0, 0, State::handshake3}, {&final2, State::handshake4}},
{{0, 0, State::handshake4}, {&sendPayload, State::xferPayload}},
{{0, 0, State::xferPayload}, {&sendEnd, State::endPayload}},
{{0, 0, State::endPayload}, {&starting1, State::handshake1}},
{{0, 1, State::start}, {&starting1, State::handshake1}},
{{0, 1, State::handshake1}, {&final1, State::handshake2}},
{{0, 1, State::handshake2}, {&starting2, State::handshake3}},
{{0, 1, State::handshake3}, {&final2, State::handshake4}},
{{0, 1, State::handshake4}, {&receivePayload, State::xferPayload}},
{{0, 1, State::xferPayload}, {&receiveEnd, State::endPayload}},
{{0, 1, State::endPayload}, {&starting1, State::handshake1}},
{{1, 0, State::start}, {&starting2, State::handshake1}},
{{1, 0, State::handshake1}, {&final2, State::handshake2}},
{{1, 0, State::handshake2}, {&starting1, State::handshake3}},
{{1, 0, State::handshake3}, {&final1, State::handshake4}},
{{1, 0, State::handshake4}, {&sendPayload, State::xferPayload}},
{{1, 0, State::xferPayload}, {&sendEnd, State::endPayload}},
{{1, 0, State::endPayload}, {&starting2, State::handshake1}},
{{1, 1, State::start}, {&starting2, State::handshake1}},
{{1, 1, State::handshake1}, {&final2, State::handshake2}},
{{1, 1, State::handshake2}, {&starting1, State::handshake3}},
{{1, 1, State::handshake3}, {&final1, State::handshake4}},
{{1, 1, State::handshake4}, {&receivePayload, State::xferPayload}},
{{1, 1, State::xferPayload}, {&receiveEnd, State::endPayload}},
{{1, 1, State::endPayload}, {&starting2, State::handshake1}}
};
class Machine
{
public:
Machine()
{
const size_t tableSize = sizeof(stateTable) / sizeof(stateTable[0]);
for (size_t row=0; row<tableSize; ++row)
{
stateChart_[stateTable[row].key] = stateTable[row].effect;
}
}
void reset(bool startsAt2, bool isReceiving)
{
stateKey_.startsAt2 = startsAt2;
stateKey_.isReceiving = isReceiving;
stateKey_.state = State::start;
}
void step()
{
StateChart::const_iterator iter = stateChart_.find(stateKey_);
assert(iter != stateChart_.end());
const StateEffect& effect = iter->second;
effect.function(*this);
stateKey_.state = effect.newState;
}
private:
typedef std::map<StateKey, StateEffect> StateChart;
StateChart stateChart_;
StateKey stateKey_;
};
int main()
{
Machine machine;
machine.reset(true, false);
for (int i=0; i<20; ++i)
{
machine.step();
}
}
. , :
- / StateEffect
- "" StateKey
- .
, Boost.StateChart wannabe.; -)