Eric Day

Thoughts, code, and other oddments.
Dark | Light

Programming - C++

state_stack.cc

Download

/*
 
An example state machine using a method stack.
 
Copyright (C) Eric Day - http://oddments.org/
All content licensed under the Creative Commons Attribution 3.0 License.
 
> gcc -o state_stack_c state_stack.c
> time ./state_stack_c
88
80
0.976u 0.000s 0:00.97 100.0%    0+0k 0+0io 0pf+0w
 
> g++ -o state_stack_cc state_stack.cc
> time ./state_stack_cc
88
80
1.696u 0.000s 0:01.69 100.0%    0+0k 0+0io 0pf+0w
 
*/
 
#include <iostream>
#include <inttypes.h>
#include <string>
#include <functional>
 
using namespace std;
 
template <class T>
class State
{
  const mem_fun_t<bool, T> *methods[8];
  uint8_t method_count;
 
public:
  State():
    method_count(0)
  {}
 
  void push(const mem_fun_t<bool, T> &method)
  {
    methods[method_count]= &method;
    method_count++;
  }
 
  void pop()
  {
    method_count--;
  }
 
  void run()
  {
    while (method_count > 0 &&
           methods[method_count - 1]->operator()(static_cast<T *>(this)))
    {
      /* No body for this while loop. */
    }
  }
};
 
/* Implementation Classes. */
class Result;
 
namespace result
{
  extern const mem_fun_t<bool, Result> ReadState;
}
 
class Result: public State<Result>
{
  string result;
 
public:
  string getResult(void)
  {
    return result;
  }
 
  void readResult(void)
  {
    push(result::ReadState);
    run();
  }
 
  bool readState(void)
  {
    result= "Moo.";
    pop();
    return true;
  }
};
 
namespace result
{
  const mem_fun_t<bool, Result> ReadState(mem_fun(&Result::readState));
}
 
class Connection;
 
namespace connection
{
  extern const mem_fun_t<bool, Connection> ConnectState;
  extern const mem_fun_t<bool, Connection> AuthenticateState;
  extern const mem_fun_t<bool, Connection> QueryState;
  extern const mem_fun_t<bool, Connection> ResultState;
}
 
class Connection: public State<Connection>
{
  bool isConnected;
  string query_str;
  Result *result;
 
public:
  Connection():
    isConnected(false),
    result(NULL)
  {}
 
  void query(string query_arg, Result &result_arg)
  {
    query_str= query_arg;
    result= &result_arg;
    push(connection::ResultState);
    push(connection::QueryState);
    run();
  }
 
  bool connectState(void)
  {
    isConnected= true;
    pop();
    push(connection::AuthenticateState);
    return true;
  }
 
  bool authenticateState(void)
  {
    pop();
    return true;
  }
 
  bool queryState(void)
  {
    if (!isConnected)
    {
      push(connection::ConnectState);
      return true;
    }
 
    pop();
    return true;
  }
 
  bool resultState(void)
  {
    result->readResult();
    pop();
    return true;
  }
};
 
namespace connection
{
const mem_fun_t<bool, Connection>
  ConnectState(mem_fun(&Connection::connectState));
const mem_fun_t<bool, Connection>
  AuthenticateState(mem_fun(&Connection::authenticateState));
const mem_fun_t<bool, Connection>
  QueryState(mem_fun(&Connection::queryState));
const mem_fun_t<bool, Connection>
  ResultState(mem_fun(&Connection::resultState));
};
 
/* Test program. */
void test(void)
{
  Connection connnection;
  Result result;
 
  connnection.query("What does a cow say?", result);
}
 
int main(void)
{
  int x;
 
  cout << sizeof(Connection) << endl;
  cout << sizeof(Result) << endl;
 
  for (x= 0; x < 5000000; x++)
    test();
 
  return 0;
}
Blog
Wiki
About
Resume
RSS
Comments

E-Mail
Launchpad
LinkedIn
Twitter
identi.ca
Facebook

OpenStack
Scale Stack
Gearman
NW Veg
Veg Food & Fit

Linux On Laptops