Общая часть
struct StateCallback {
typedef void (*cb_fn)(void*,int); cb_fn cb; void* ctx;
StateCallback(cb_fn cb=0,void *ctx=0) : cb(cb), ctx(ctx) {}
void operator() (int s) { if (cb) cb(ctx,s); }
operator bool() { return !!cb; }
};
struct ChangeStateCallback {
typedef void (*cb_fn)(void*,int,int); cb_fn cb; void* ctx;
ChangeStateCallback(cb_fn cb=0,void *ctx=0) : cb(cb), ctx(ctx) {}
void operator() (int a,int b) { if (cb) cb(ctx,a,b); }
operator bool() { return !!cb; }
};
template<class ST,class T> struct FSM : ST {
FSM() { pstate=-1; state=0; for(int i=0;i<ST::stMAX;++i) vst[i]=nop; }
void step() {
if (pstate!=state) {
if (pstate>=0) {
leave(pstate);
change(pstate,state);
}
enter(state);
pstate=state;
}
int saved_state=state;
before(state);
vst[state]((T*)this);
after(saved_state);
}
int getState() { return state; }
void setState(int s) { state=s; }
ChangeStateCallback change;
StateCallback leave, enter, before, after;
ChangeStateCallback operator() (void (*cb)(T* p,int a,int b)) {
return ChangeStateCallback((ChangeStateCallback::cb_fn)cb,this);
}
StateCallback operator() (void (*cb)(T* p,int a)) {
return StateCallback((StateCallback::cb_fn)cb,this);
}
protected:
typedef void (*vst_fn)(T*);
int pstate, state; vst_fn vst[ST::stMAX];
static void nop(T*) {}
};
Пример объявления конкретной FSM
// header
struct States { enum { st_S0, st_S1, st_S2, stMAX }; };
struct FSM1 : FSM<States,FSM1> {
int n0, n1, n2;
FSM1();
const char* getName(int s) { return names[s]; }
private:
const char* names[stMAX];
};
// implementation
FSM1::FSM1() {
struct A {
static void S0(FSM1 *p) {
p->n0++;
int st=p->getState();
p->setState(st_S2);
}
static void S1(FSM1 *p) {
p->n1++;
if (p->n1>3) p->setState(st_S0);
}
static void S2(FSM1 *p) {
p->n2++;
if (p->n2>2) p->setState(st_S1);
}
};
n0=0; n1=0; n2=0;
vst[st_S0]=A::S0;
vst[st_S1]=A::S1;
vst[st_S2]=A::S2;
for(int i=0;i<stMAX;++i) names[i]="unknown";
names[st_S0]="S0";
names[st_S1]="S1";
names[st_S2]="S2";
}
Как используется:
#include <stdio.h>
int main(int argc,char** argv) {
FSM1 sm;
struct Hook {
static void change(FSM1* p,int s1,int s2) {
const char *n1, *n2;
n1=p->getName(s1);
n2=p->getName(s2);
printf("%s->%s\n",n1,n2);
}
static void enter (FSM1* p,int s) { printf("\t%s{ ",p->getName(s)); }
static void leave (FSM1* p,int s) { printf(" }%s\n",p->getName(s)); }
static void before(FSM1* p,int s) { printf("(%s",p->getName(s)); }
static void after (FSM1* p,int s) { printf(")"); }
};
sm.change=sm(Hook::change);
sm.enter =sm(Hook::enter);
sm.leave =sm(Hook::leave);
sm.before=sm(Hook::before);
sm.after =sm(Hook::after);
for(int i=0;i<15;++i) sm.step();
printf("\n");
return 0;
}
Вобщем простенький конечный автомат. Жду критику