Transition.cc
Go to the documentation of this file.00001 #include "Transition.h"
00002 #include "StateNode.h"
00003 #include "Wireless/Wireless.h"
00004 #include "Sound/SoundManager.h"
00005 #include "Events/EventRouter.h"
00006 #include "Shared/debuget.h"
00007
00008 std::list<Transition*> Transition::firing;
00009
00010 Transition::~Transition() {
00011 ASSERT(!isActive(),"Transition " << getName() << " destructing while active (forgot stop()?)");
00012 ASSERT(std::find(firing.begin(),firing.end(),this)==firing.end(),"Transition " << getName() << " still active in firing queue!");
00013 if(eventData) {
00014 delete eventData;
00015 eventData = NULL;
00016 }
00017 }
00018
00019 void Transition::stop() {
00020 eventData = NULL;
00021 firing.remove(this);
00022 BehaviorBase::stop();
00023 }
00024
00025 void Transition::fire() {
00026 ASSERT(eventData==NULL, getName() << " firing with event still buffered")
00027 if(std::find(firing.begin(), firing.end(), this) == firing.end())
00028 firing.push_back(this);
00029 else {
00030 std::cout << "Trying to fire " << getName() << " but it's already on the call stack." << std::endl;
00031 showFiring();
00032 }
00033
00034 if(firing.front()==this)
00035 fireDownCallStack();
00036 }
00037
00038 void Transition::fire(const EventBase& ev) {
00039 ASSERT(eventData==NULL, getName() << " firing with previous event already buffered, overwriting...");
00040 if ( eventData != NULL )
00041 std::cout << "Previous=" << eventData->getName() << " @ " << event->getTimeStamp()
00042 << " New=" << ev.getName() << " @ " << ev.getTimeStamp() << std::endl;
00043 eventData = ev.clone();
00044 if(std::find(firing.begin(), firing.end(), this) == firing.end())
00045 firing.push_back(this);
00046 else {
00047 std::cout << "Trying to fire " << getName() << " but it's already on the call stack." << std::endl;
00048 showFiring();
00049 }
00050
00051 if(firing.front()==this)
00052 fireDownCallStack();
00053 }
00054
00055 void Transition::fireDownCallStack() {
00056 while(!firing.empty())
00057 firing.front()->doFire();
00058 }
00059
00060 void Transition::doFire() {
00061 ASSERTRET(isActive(),"doFire from " << getName() << " but not active");
00062
00063 addReference();
00064
00065 if(soundFile.size()!=0)
00066 sndman->playFile(soundFile);
00067 #ifdef PLATFORM_APERIOS
00068 if ( !speechText.empty() )
00069 sout->printf("Speak: %s\n",speechText.c_str());
00070 #else
00071 if ( !speechText.empty() )
00072 sndman->speak(speechText);
00073 #endif
00074
00075 erouter->postEvent(EventBase::stateTransitionEGID,
00076 reinterpret_cast<size_t>(this),
00077 EventBase::activateETID,0,getName(),1);
00078
00079
00080 firing.push_front(NULL);
00081
00082 const EventBase* eventDataSave = eventData;
00083 for(unsigned int i=0; i<srcs.size(); i++) {
00084 try {
00085 if(srcs[i]->isActive())
00086 srcs[i]->stop();
00087 } catch(const std::exception& ex) {
00088 std::cout << "Exception '" << ex.what() << "' thrown during transition "
00089 << getName() << ", deactivating source node " << srcs[i]->getName() << std::endl;
00090 } catch(...) {
00091 std::cout << "Exception thrown during transition " << getName()
00092 << ", deactivating source node " << srcs[i]->getName() << std::endl;
00093 firing.pop_front();
00094 removeReference();
00095 throw;
00096 }
00097 }
00098
00099 for(unsigned int i=0; i<dsts.size(); i++) {
00100 const EventBase* prevEvent = dsts[i]->event;
00101 dsts[i]->event=eventDataSave;
00102 try {
00103 if(!dsts[i]->isActive())
00104 dsts[i]->start();
00105 } catch(const std::exception& ex) {
00106 std::cout << "Exception '" << ex.what() << "' thrown during transition "
00107 << getName() << ", activating destination node " << dsts[i]->getName() << std::endl;
00108 } catch(...) {
00109 std::cout << "Exception thrown during transition " << getName()
00110 << ", activating destination node " << dsts[i]->getName() << std::endl;
00111 firing.pop_front();
00112 removeReference();
00113 throw;
00114 }
00115 dsts[i]->event=prevEvent;
00116 }
00117
00118 delete eventDataSave;
00119 firing.pop_front();
00120 erouter->postEvent(EventBase::stateTransitionEGID,
00121 reinterpret_cast<size_t>(this),
00122 EventBase::deactivateETID,0,getName(),0);
00123
00124 if ( isActive() ) {
00125 if ( firing.size()>0 ) {
00126 ASSERTIF(firing.front()==this, "doFire from " << getName() << " but it's not my turn, should be " << firing.front()->getName()) {
00127 firing.pop_front();
00128 }
00129 }
00130 } else {
00131 ASSERT(std::find(firing.begin(),firing.end(),this)==firing.end(),"Transition still in firing queue following doFire, subclass overridden stop() and forgot to call Transition::stop()?");
00132 }
00133
00134 removeReference();
00135 }
00136
00137 void Transition::showFiring() {
00138 std::cout << "firing =";
00139 for (std::list<Transition*>::const_iterator it = firing.begin();
00140 it != firing.end(); it++) {
00141 std::cout << " ";
00142 if ( *it == NULL )
00143 std::cout << "0";
00144 else
00145 std::cout << (*it)->instanceName;
00146 }
00147 std::cout << std::endl;
00148 }
00149
00150 std::string Transition::getName() const {
00151 if(instanceName != getClassName()) {
00152 return instanceName;
00153 } else {
00154 std::string ans;
00155 if ( srcs.size() == 1 )
00156 ans = srcs[0]->getName();
00157 else {
00158 ans = '{';
00159 for(unsigned int i=0; i<srcs.size(); i++)
00160 ans += srcs[i]->getName() + (i<srcs.size()-1?',':'}');
00161 }
00162 ans += ">==" + instanceName + "==>";
00163 if ( dsts.size() == 1 )
00164 ans += dsts[0]->getName();
00165 else {
00166 ans += '{';
00167 for(unsigned int i=0; i<dsts.size(); i++)
00168 ans += dsts[i]->getName() + (i<dsts.size()-1?',':'}');
00169 }
00170 return ans;
00171 }
00172 }
00173
00174
00175
00176
00177
00178