Eric DayThoughts, code, and other oddments. |
Dark | Light |
|
|
|
Programming - Cstate_stack.c/* An example state machine using a function stack. Copyright (C) Eric Day - http://oddments.org/ All content licensed under the Creative Commons Attribution 3.0 License. This compares the C and C++ versions of state_stack. > 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 <assert.h> #include <inttypes.h> #include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> /* Structs. */ struct connection; typedef struct connection connection_st; typedef bool (connection_state_fn)(connection_st *connection); struct result; typedef struct result result_st; typedef bool (result_state_fn)(result_st *result); struct connection { connection_state_fn *state_stack[8]; uint8_t state_current; bool is_connected; char *query; result_st *result; }; struct result { result_state_fn *state_stack[8]; uint8_t state_current; char *result; }; /* Function declarations. */ void connection_init(connection_st *connection); void connection_deinit(connection_st *connection); void connection_state_push(connection_st *connection, connection_state_fn *state_fn); void connection_state_pop(connection_st *connection); void connection_state_run(connection_st *connection); void connection_query(connection_st *connection, char *query, result_st *result); bool connection_connect_state(connection_st *connection); bool connection_authenticate_state(connection_st *connection); bool connection_query_state(connection_st *connection); bool connection_result_state(connection_st *connection); void result_init(result_st *result); void result_deinit(result_st *result); void result_state_push(result_st *result, result_state_fn *state_fn); void result_state_pop(result_st *result); void result_state_run(result_st *result); char *result_get_result(result_st *result); void result_read_result(result_st *result); bool result_read_state(result_st *result); /* Function definitions. */ void connection_init(connection_st *connection) { connection->state_current= 0; connection->is_connected= false; connection->query= NULL; connection->result= NULL; } void connection_deinit(connection_st *connection) { if (connection->query != NULL) free(connection->query); } void connection_state_push(connection_st *connection, connection_state_fn *state_fn) { connection->state_stack[connection->state_current]= state_fn; connection->state_current++; } void connection_state_pop(connection_st *connection) { connection->state_current--; } void connection_state_run(connection_st *connection) { while (connection->state_current > 0 && connection->state_stack[connection->state_current - 1](connection)) { } } void connection_query(connection_st *connection, char *query, result_st *result) { connection->query= strdup(query); connection->result= result; connection_state_push(connection, connection_result_state); connection_state_push(connection, connection_query_state); connection_state_run(connection); } bool connection_connect_state(connection_st *connection) { connection->is_connected= true; connection_state_pop(connection); connection_state_push(connection, connection_authenticate_state); return true; } bool connection_authenticate_state(connection_st *connection) { connection_state_pop(connection); return true; } bool connection_query_state(connection_st *connection) { if (!connection->is_connected) { connection_state_push(connection, connection_connect_state); return true; } connection_state_pop(connection); return true; } bool connection_result_state(connection_st *connection) { result_read_result(connection->result); connection_state_pop(connection); return true; } void result_init(result_st *result) { result->state_current= 0; result->result= NULL; } void result_deinit(result_st *result) { if (result->result != NULL) free(result->result); } void result_state_push(result_st *result, result_state_fn *state_fn) { result->state_stack[result->state_current]= state_fn; result->state_current++; } void result_state_pop(result_st *result) { result->state_current--; } void result_state_run(result_st *result) { while (result->state_current > 0 && result->state_stack[result->state_current - 1](result)) { } } char *result_get_result(result_st *result) { return result->result; } void result_read_result(result_st *result) { result_state_push(result, result_read_state); result_state_run(result); } bool result_read_state(result_st *result) { result->result= strdup("Moo"); result_state_pop(result); return true; } /* Test program. */ void test(void) { connection_st connection; result_st result; connection_init(&connection); result_init(&result); connection_query(&connection, "What does a cow say?", &result); connection_deinit(&connection); result_deinit(&result); } int main(void) { int x; printf("%zu\n", sizeof(connection_st)); printf("%zu\n", sizeof(result_st)); for (x= 0; x < 5000000; x++) test(); return 0; } |
Blog Wiki About Resume RSS Comments Launchpad identi.ca OpenStack Scale Stack Gearman NW Veg Veg Food & Fit |
|
Copyright (C) Eric Day - eday@oddments.org All content licensed under the Creative Commons Attribution 3.0 License. Hosted by Rackspace Cloud |
|