Question

I have used it in another programming language and It's very usefull.

I cannot find anything about this for C++.

Let's for example take the following code:

void change();

enum
{
    end = 0,
    gmx
}

int
    gExitType;

int main()
{
    gExitType = end;
    SetTimer(&change, 10000, 0);
    return 0;
}

void ApplicationExit()
{
    switch (gExitType)
    {
        case end:
            printf("This application was ended by the server");
        case gmx:
            printf("This application was ended by the timer");
    }
    ::exit(0);
}

void change()
{
    gExitType = gmx;
    ApplicationExit();
}

That's kind of how we would do it in C++, but when using state machine/automata I could do something like this in the other language:

void change();

int main()
{
    state exitType:end;
    SetTimer(&change, 10000, 0);
    return 0;
}

void ApplicationExit() <exitType:end>
{
    printf("This application was ended by the server");
}

void ApplicationExit() <exitType:gmx>
{
    printf("This application ended by the timer");
}

void change()
{
    state exitType:gmx;
    ApplicationExit();
}

In my opition this is a really elegant way to achieve things. How would I do this in C++? This code doesn't seem to work (obviously as I cannot find anything automata related to C++)

To clarify my opinion:

So what are the advantages to using this technique? Well, as you can clearly see the code is smaller; granted I added an enum to the first version to make the examples more similar but the ApplicationExit functions are definately smaller. It's also alot more explicit - you don't need large switch statements in functions to determine what's going on, if you wanted you could put the different ApplicationExits in different files to handle different sets of code independently. It also uses less global variables.

Was it helpful?

Solution 2

For this particular example, you could use objects and polymorphism to represent the different states. For example:

class StateObject
{
    public:
        virtual void action(void) = 0;
};

class EndedBy : public StateObject
{
    private:
        const char *const reason;

    public:
        EndedBy( const char *const reason_ ) : reason( reason_ ) { }
        virtual void action(void)
        {
            puts(reason);
        }
};

EndedBy EndedByServer("This application was ended by the server");
EndedBy EndedByTimer ("This application ended by the timer");

StateObject *state = &EndedByServer;

void change()
{
    state = &EndedByTimer;
}

void ApplicationExit()
{
    state->action();
    ::exit(0);
}

int main()
{
    SetTimer(&change, 10000, 0);

    // whatever stuff here... 
    // presumably eventually causes ApplicationExit() to get called before return 0;

    return 0;
}

That said, this isn't great design, and it isn't an FSM in the general sense. But, it would implement your immediate need.

You might look up the State Pattern (one reference: http://en.wikipedia.org/wiki/State_pattern ) for a more general treatment of this pattern.

The basic idea, though, is that each state is a subclass of some common "state" class, and you can use polymorphism to determine the different actions and behaviors represented by each state. A pointer to the common "state" base class then keeps track of the state you're currently in.

The state objects may be different types, or as in my example above, different instances of the same object configured differently, or a blend.

OTHER TIPS

There are C++ libraries like Boost.statechart that specifically try to provide rich support for encoding state machines:
http://www.boost.org/doc/libs/1_54_0/libs/statechart/doc/tutorial.html

Besides this, one very elegant way to encode certain types of state machines is by defining them as a couroutine:
http://c2.com/cgi/wiki?CoRoutine
http://eli.thegreenplace.net/2009/08/29/co-routines-as-an-alternative-to-state-machines/

Coroutines are not directly supported in C++, but there are two possible approaches for implementing them:

1) Using a technique similar to implementing a duff's device, explained in details here:
http://blog.think-async.com/search/label/coroutines
This is very similar to how C#'s iterators work for example and one limitation is that yielding form the coroutine can be done only from the topmost function in the coroutine call-stack. OTOH, the advantage of this method is that very little memory is required for each instance of the coroutine.

2) Allocating a separate stack and registers space for each coroutine.
This essentially makes the coroutine a full-blown thread of execution with the only difference that the user has full responsibility for the thread scheduling (also known as cooperative multi-tasking).
A portable implementation is available from boost:
http://www.boost.org/doc/libs/1_54_0/libs/coroutine/doc/html/coroutine/intro.html

You can use Template value specialization over an int to achieve pretty much what you want.

(Sorry I'm at my tablet so I cannot provide an example, I will update on Sunday)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top