FREE Subscription to Dr. Dobb’s Digest: Same Great Content, New Digital Edition
Site Archive (Complete)
C++
Email
Print
Reprint

add to:
Del.icio.us
Digg
Google
Furl
Slashdot
Y! MyWeb
Blink
December 01, 2005

Hierarchical State Machine Design in C++

(Page 7 of 7)

December, 2005: Hierarchical State Machine Design in C++

Listing 4

#include "stdafx.h"
#include "resource.h"          
#include "pelican_static.h"

HWND hWnd_=0;

void Pelican::Off::on_enter(Pelican*,State<Pelican>* old_state){
    if (old_state && old_state->derives_from(this)) {
        printf("-already in Off");
        return;
    }
    printf("->Off::on_enter");
    EndDialog(hWnd_, 0);
}

void Pelican::vehiclesEnabled::on_enter(Pelican* p,State<Pelican>* old_state){
    if (old_state && old_state->derives_from(this)) {
        printf("-already in vehiclesEnabled");
        return;
    }
    operational::on_enter(p,old_state);

    printf("->vehiclesEnabled::on_enter");
    signalPedestrians(DONT_WALK);
}

void Pelican::vehiclesGreen::on_enter(Pelican* p,State<Pelican>* old_state){
    if (old_state && old_state->derives_from(this)) {
        printf("-already in vehiclesGreen");
        return;
    }
    vehiclesEnabled::on_enter(p,old_state);

    printf("->vehiclesGreen::on_enter");

    m_isPedestrianWaiting=FALSE;
    SetDlgItemText(hWnd_, IDC_STATE, "vehiclesGreen");
    SetTimer(hWnd_, 1, VEHICLES_GREEN_MIN_TOUT, 0);
    signalVehicles(GREEN); 
}

void Pelican::vehiclesGreenInt::on_enter(Pelican* p,State<Pelican>* old_state){
    if (old_state && old_state->derives_from(this)) {
        printf("-already in vehiclesGreenInt");
        return;
    }
    vehiclesEnabled::on_enter(p,old_state);

    printf("->vehiclesGreenInt::on_enter");

    SetDlgItemText(hWnd_, IDC_STATE, "vehiclesGreenInt"); 
    signalVehicles(GREEN); 
}

void Pelican::vehiclesYellow::on_enter(Pelican* p,State<Pelican>* old_state){
    if (old_state && old_state->derives_from(this)) {
        printf("-already in vehiclesYellow");
        return;
    }
    vehiclesEnabled::on_enter(p,old_state);
    printf("->vehiclesYellow::on_enter");

    SetDlgItemText(hWnd_, IDC_STATE, "vehiclesYellow");
    SetTimer(hWnd_, 1, VEHICLES_YELLOW_TOUT, 0);
    signalVehicles(YELLOW);
}

void Pelican::pedestriansEnabled::on_enter(Pelican* p,State<Pelican>* old_state){ 
    if (old_state && old_state->derives_from(this)) {
        printf("-already in pedestriansEnabled");
        return;
    }
    operational::on_enter(p,old_state);

    printf("->pedestriansEnabled::on_enter");

    signalVehicles(RED); 
}

void Pelican::pedestriansWalk::on_enter(Pelican* p,State<Pelican>* old_state){
    if (old_state && old_state->derives_from(this)) {
        printf("-already in pedestriansWalk");
        return;
    }
    pedestriansEnabled::on_enter(p,old_state);

    printf("->pedestriansWalk::on_enter");

    SetDlgItemText(hWnd_, IDC_STATE, "pedestriansWalk");
    signalPedestrians(WALK);
    UINT_PTR t=SetTimer(hWnd_, 1, PEDESTRIANS_WALK_TOUT, 0);
}

void Pelican::pedestriansFlash::on_enter(Pelican* p,State<Pelican>* old_state){
    if (old_state && old_state->derives_from(this)) {
        printf("-already in pedestriansFlash");
        return;
    }
    pedestriansEnabled::on_enter(p,old_state);

    printf("->pedestriansFlash::on_enter");

    SetDlgItemText(hWnd_, IDC_STATE, "pedestriansFlash");
    SetTimer(hWnd_, 1, PEDESTRIANS_FLASH_TOUT, 0);
    pedestrianFlashCtr_ = PEDESTRIANS_FLASH_NUM*2 + 1;
}

void Pelican::vehiclesEnabled::on_exit(Pelican* p,State<Pelican>* new_state){ 
    if (new_state && new_state->derives_from(this)) {
        printf("-stay in vehiclesEnabled");
        return;
    }

    printf("->vehiclesEnabled::on_exit");

    operational::on_exit(p,new_state);
}


void Pelican::pedestriansWalk::on_exit(Pelican* p,State<Pelican>* new_state){ 
    if (new_state && new_state->derives_from(this)) {
        printf("-stay in pedestriansWalk");
        return;
    }
    printf("->pedestriansWalk::on_exit");

    KillTimer(hWnd_, 1); 
    pedestriansEnabled::on_exit(p,new_state);
}

void Pelican::vehiclesYellow::on_exit(Pelican* p,State<Pelican>* new_state){
    if (new_state && new_state->derives_from(this)) {
        printf("-stay in vehiclesYellow");
        return;
    }
    printf("->vehiclesYellow::on_exit");

    KillTimer(hWnd_, 1);
    vehiclesEnabled::on_exit(p,new_state);
}
void Pelican::vehiclesGreen::on_exit(Pelican* p,State<Pelican>* new_state){
    if (new_state && new_state->derives_from(this)) {
        printf("-stay in vehiclesGreen");
        return;
    }

    printf("->vehiclesGreen::on_exit");
    
    KillTimer(hWnd_, 1); 
    
    vehiclesEnabled::on_exit(p,new_state);
}

void Pelican::pedestriansFlash::on_exit(Pelican* p,State<Pelican>* new_state){
    if (new_state && new_state->derives_from(this)) {
        printf("-stay in pedestriansFlash");
        return;
    }

    printf("->pedestriansFlash::on_exit");

    KillTimer(hWnd_, 1);

    pedestriansEnabled::on_exit(p,new_state);
}

State<Pelican>* Pelican::operational::off(Pelican* p,const boost::any&){
    return &p->m_Off;    //can simply return 0;
}

State<Pelican>* Pelican::vehiclesGreen::pedestrianWaiting(Pelican*,const 
  boost::any&){
    m_isPedestrianWaiting = TRUE;
    return this;
}
State<Pelican>* Pelican::vehiclesGreen::timeout(Pelican* p,const boost::any&){
    if (m_isPedestrianWaiting)return &p->m_vehiclesYellow;
    else                      return &p->m_vehiclesGreenInt;
}

State<Pelican>* Pelican::vehiclesGreenInt::pedestrianWaiting(Pelican* p,const 
  boost::any&){
    return &p->m_vehiclesYellow;
}

State<Pelican>* Pelican::vehiclesYellow::timeout(Pelican* p,const boost::any&){
    return  &p->m_pedestriansWalk;
}

State<Pelican>* Pelican::pedestriansWalk::timeout(Pelican* p,const 
  boost::any&){
    return &p->m_pedestriansFlash;
}

State<Pelican>* Pelican::pedestriansFlash::timeout(Pelican* p,const boost::any&){
    if (--pedestrianFlashCtr_ == 0) //done flashing?
        return &p->m_vehiclesGreen; //note the change from Miro Samek's--
                                  //we enter derived state directly
    
    //even counter?DONT_WALK:BLANK
    signalPedestrians((pedestrianFlashCtr_ & 1) == 0? DONT_WALK : BLANK);

    return this;
}

Pelican::Pelican(){}

void Pelican::init(){
    operational::signalVehicles(operational::RED);
    operational::signalPedestrians(operational::DONT_WALK);

    //make the initial transition. note the change from Miro Samek's--
    //we enter derived state directly
    transition(&m_vehiclesGreen);
}

void Pelican::operational::signalVehicles(enum VehiclesSignal sig) {
   ShowWindow(GetDlgItem(hWnd_, IDC_RED), sig == RED);
   ShowWindow(GetDlgItem(hWnd_, IDC_YELLOW), sig == YELLOW);
   ShowWindow(GetDlgItem(hWnd_, IDC_GREEN), sig == GREEN);
}

void Pelican::operational::signalPedestrians(enum PedestriansSignal sig) {
   ShowWindow(GetDlgItem(hWnd_, IDC_DONT_WALK), sig == DONT_WALK);
   ShowWindow(GetDlgItem(hWnd_, IDC_BLANK), sig == BLANK);
   ShowWindow(GetDlgItem(hWnd_, IDC_WALK), sig == WALK);
}

BOOL CALLBACK Pelican::dlgproc(HWND hwnd,UINT iMsg,WPARAM wParam, LPARAM lParam){
   static Pelican app;
   Pelican::Event e(0);

   switch (iMsg) {
    case WM_INITDIALOG:
        hWnd_=hwnd;
        app.init();
        SendMessage(hwnd, WM_SETICON, (WPARAM)TRUE, (LPARAM)LoadIcon(GetModuleHandle(0), MAKEINTRESOURCE(IDI_ICON1)));
        break;
    case WM_TIMER:
        e =State<Pelican>::timeout;
        break;
    case WM_COMMAND:                     
        switch (LOWORD(wParam)) {
        case IDCANCEL:
            e =State<Pelican>::off;
            break;
        case IDC_PEDESTRIAN_WAITING:
            e = State<Pelican>::pedestrianWaiting;
            break;
        }      
   }

   if(e){
    boost::any arg;
    if(0==app.dispatch(e,arg))
        EndDialog(hWnd_, 0);
   }
   return FALSE;            
}

int main(int argc, char* argv[]){
    return DialogBox(GetModuleHandle(0), MAKEINTRESOURCE(IDD_DIALOG), 0, 
      Pelican::dlgproc);                  
}

Previous Page | 1 | 2 | 3 | 4 | 5 | 6 | 7
TOP 5 ARTICLES
No Top Articles.



MICROSITES
FEATURED TOPIC

ADDITIONAL TOPICS

INFO-LINK