|
INET Framework for OMNeT++/OMNEST
|
00001 // 00002 // Copyright (C) 2006 Andras Varga and Levente Meszaros 00003 // 00004 // This program is free software; you can redistribute it and/or 00005 // modify it under the terms of the GNU Lesser General Public License 00006 // as published by the Free Software Foundation; either version 2 00007 // of the License, or (at your option) any later version. 00008 // 00009 // This program is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 // GNU Lesser General Public License for more details. 00013 // 00014 // You should have received a copy of the GNU Lesser General Public License 00015 // along with this program; if not, see <http://www.gnu.org/licenses/>. 00016 // 00017 00018 #ifndef __INET_FSMA_H 00019 #define __INET_FSMA_H 00020 00021 #include "INETDefs.h" 00022 00023 /* 00024 This is an alternative FSM implementation. 00025 00026 Here is an example: 00027 00028 FSMA_Switch(fsm) 00029 { 00030 FSMA_State(X) 00031 { 00032 FSMA_Event_Transition(XY, isFoo, Y, 00033 doFoo); 00034 FSMA_No_Event_Transition(XZ, isFooBar, Z, 00035 doFooBar); 00036 } 00037 FSMA_State(Y) 00038 { 00039 FSMA_Event_Transition(YX, isBar, X, 00040 doBar); 00041 } 00042 FSMA_State(Z) 00043 { 00044 FSMA_Event_Transition(ZX, isBaz, X, 00045 doBaz); 00046 } 00047 } 00048 00049 After macro expansion, a state machine code looks like something along 00050 these lines: 00051 00052 bool ___is_event = true; 00053 bool ___exit = false; 00054 int ___c = 0; 00055 cFSM ___fsm = fsm; 00056 while (!___exit && (___c++ < FSM_MAXT || opp_error(eINFLOOP, ___fsm->getStateName())) 00057 { 00058 if (condition_seen = false, ___exit = true, ___fsm->getState() == X) 00059 { 00060 if (!___is_event) 00061 { 00062 if (condition_seen) 00063 error("..."); 00064 // enter code 00065 } 00066 condition_seen = true; if (isFoo && ___is_event) 00067 { 00068 EV << "firing " << XY << " transition for " << ___fsm->getName() << endl; 00069 doFoo; 00070 ___fsm->setState(Y, "Y"); 00071 ___is_event = false; 00072 ___exit = false; 00073 continue; 00074 } 00075 condition_seen = true; if (isFooBar && !___is_event) 00076 { 00077 EV << "firing " << XZ << " transition for " << ___fsm->getName() << endl; 00078 doFooBar; 00079 ___fsm->setState(Z, "Z"); 00080 ___exit = false; 00081 continue; 00082 } 00083 } 00084 if (condition_seen = false, ___exit = true, ___fsm->getState() == Y) 00085 { 00086 condition_seen = true; if (isBar && ___is_event) 00087 { 00088 EV << "firing " << YX << " transition for " << ___fsm->getName() << endl; 00089 doVar; 00090 ___fsm->setState(X, "X"); 00091 ___is_event = false; 00092 ___exit = false; 00093 continue; 00094 } 00095 } 00096 } 00097 */ 00098 00099 #define FSMA_Switch(fsm) \ 00100 bool ___is_event = true; \ 00101 bool ___exit = false; \ 00102 bool ___condition_seen = false; \ 00103 int ___c = 0; \ 00104 cFSM *___fsm = &fsm; \ 00105 EV << "processing event in state machine " << (fsm).getName() << endl; \ 00106 while (!___exit && (___c++ < FSM_MAXT || (opp_error(eINFLOOP, (fsm).getStateName()), 0))) 00107 00108 #define FSMA_Print(exiting) \ 00109 (ev << "FSM " << ___fsm->getName() \ 00110 << ((exiting) ? ": leaving state " : ": entering state ") \ 00111 << ___fsm->getStateName() << endl) 00112 00113 #define FSMA_State(s) if (___condition_seen = false, ___exit = true, ___fsm->getState() == (s)) 00114 00115 #define FSMA_Event_Transition(transition, condition, target, action) \ 00116 ___condition_seen = true; if ((condition) && ___is_event) \ 00117 { \ 00118 ___is_event = false; \ 00119 FSMA_Transition(transition, (condition), target, action) 00120 00121 #define FSMA_No_Event_Transition(transition, condition, target, action) \ 00122 ___condition_seen = true; if ((condition) && !___is_event) \ 00123 { \ 00124 FSMA_Transition(transition, (condition), target, action) 00125 00126 #define FSMA_Transition(transition, condition, target, action) \ 00127 FSMA_Print(true); \ 00128 EV << "firing " << #transition << " transition for " << ___fsm->getName() << endl; \ 00129 action; \ 00130 ___fsm->setState(target, #target); \ 00131 FSMA_Print(false); \ 00132 ___exit = false; \ 00133 continue; \ 00134 } 00135 00136 #define FSMA_Enter(action) \ 00137 if (!___is_event) \ 00138 { \ 00139 if (___condition_seen) \ 00140 error("FSMA_Enter() must precede all FSMA_*_Transition()'s in the code"); \ 00141 action; \ 00142 } 00143 00144 #endif 00145