00001 /*************************************************************************** 00002 tag: Peter Soetens Tue Dec 21 22:43:07 CET 2004 SimulationThread.cxx 00003 00004 SimulationThread.cxx - description 00005 ------------------- 00006 begin : Tue December 21 2004 00007 copyright : (C) 2004 Peter Soetens 00008 email : peter.soetens@mech.kuleuven.ac.be 00009 00010 *************************************************************************** 00011 * This library is free software; you can redistribute it and/or * 00012 * modify it under the terms of the GNU General Public * 00013 * License as published by the Free Software Foundation; * 00014 * version 2 of the License. * 00015 * * 00016 * As a special exception, you may use this file as part of a free * 00017 * software library without restriction. Specifically, if other files * 00018 * instantiate templates or use macros or inline functions from this * 00019 * file, or you compile this file and link it with other files to * 00020 * produce an executable, this file does not by itself cause the * 00021 * resulting executable to be covered by the GNU General Public * 00022 * License. This exception does not however invalidate any other * 00023 * reasons why the executable file might be covered by the GNU General * 00024 * Public License. * 00025 * * 00026 * This library is distributed in the hope that it will be useful, * 00027 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00028 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 00029 * Lesser General Public License for more details. * 00030 * * 00031 * You should have received a copy of the GNU General Public * 00032 * License along with this library; if not, write to the Free Software * 00033 * Foundation, Inc., 59 Temple Place, * 00034 * Suite 330, Boston, MA 02111-1307 USA * 00035 * * 00036 ***************************************************************************/ 00037 00038 00039 00040 #include "SimulationThread.hpp" 00041 #include "../os/TimeService.hpp" 00042 #include "SimulationActivity.hpp" 00043 #include "../Logger.hpp" 00044 #include "../os/threads.hpp" 00045 #include "../os/MainThread.hpp" 00046 00047 #include "../os/StartStopManager.hpp" 00048 namespace RTT { 00049 using namespace extras; 00050 namespace 00051 { 00052 // Stop it before the application quits. 00053 void stopSIMThread() 00054 { 00055 SimulationThread::Release(); 00056 } 00057 00058 os::CleanupFunction SIMCleanup( &stopSIMThread ); 00059 } 00060 } 00061 00062 namespace RTT { 00063 using namespace extras; 00064 using namespace os; 00065 00066 // The static class variables 00067 SimulationThreadPtr SimulationThread::_instance; 00068 00069 SimulationThreadPtr SimulationThread::Instance(double period) 00070 { 00071 if ( !_instance ) 00072 { 00073 _instance.reset( new SimulationThread(period) ); 00074 } 00075 00076 return _instance; 00077 } 00078 00079 bool SimulationThread::Release() 00080 { 00081 _instance.reset(); 00082 return true; 00083 } 00084 00085 00086 SimulationThread::SimulationThread(double period) 00087 : TimerThread( os::LowestPriority, 00088 "SimulationThread", 00089 period), 00090 beat( TimeService::Instance() ), maxsteps_(0), sim_running(false) 00091 { 00092 Logger::In in("SimulationThread"); 00093 this->setScheduler(ORO_SCHED_OTHER); 00094 Logger::log() << Logger::Info << this->getName() <<" created with "<< this->getPeriod() <<"s periodicity"; 00095 Logger::log() << Logger::Info << " and priority " << this->getPriority() << Logger::endl; 00096 } 00097 00098 SimulationThread::~SimulationThread() 00099 { 00100 this->stop(); 00101 } 00102 00103 bool SimulationThread::isRunning() const 00104 { 00105 return sim_running || Thread::isRunning(); 00106 } 00107 00108 bool SimulationThread::start() 00109 { 00110 maxsteps_ = 0; 00111 return os::Thread::start(); 00112 } 00113 00114 bool SimulationThread::start(unsigned int maxsteps) 00115 { 00116 if (maxsteps == 0) 00117 return false; 00118 maxsteps_ = maxsteps; 00119 return os::Thread::start(); 00120 } 00121 00122 bool SimulationThread::run(unsigned int ms) 00123 { 00124 if ( ms == 0 || this->isRunning() || this->initialize() == false ) 00125 return false; 00126 unsigned int cur = 0; 00127 this->sim_running = true; 00128 while( cur != ms ) { 00129 ++cur; 00130 TimerThread::step(); 00131 beat->secondsChange(this->getPeriod()); 00132 } 00133 this->sim_running = false; 00134 this->finalize(); 00135 return true; 00136 } 00137 os::ThreadInterface* SimulationThread::simthread() { 00138 return os::MainThread::Instance(); 00139 } 00140 00141 bool SimulationThread::initialize() 00142 { 00143 Logger::In in("SimulationThread"); 00144 Logger::log() << Logger::Info << "SimulationThread takes over system time."<<Logger::nl; 00145 Logger::log() << Logger::Info << "System time will increase significantly faster."<<Logger::endl; 00146 00147 // we will update the clock in step() 00148 beat->enableSystemClock( false ); 00149 00150 cursteps = 0; 00151 // No TimerThread::initialize() to allow 'freeze' 00152 return true; 00153 } 00154 00155 void SimulationThread::finalize() 00156 { 00157 Logger::In in("SimulationThread"); 00158 Logger::log() << Logger::Info << "SimulationThread releases system time."<<Logger::endl; 00159 // release systemclock again. 00160 beat->enableSystemClock( true ); 00161 00162 // DO NOT CALL TimerThread::finalize(), since we want to be able to start/stop the 00163 // SimulationThread and inspect the activities still running. 00164 } 00165 00166 void SimulationThread::step() 00167 { 00168 ++cursteps; 00169 00170 if ( maxsteps_ == 0 || cursteps < maxsteps_ + 1 ) { 00171 TimerThread::step(); 00172 beat->secondsChange(this->getPeriod()); 00173 } 00174 00175 // call stop once : 00176 if ( cursteps == maxsteps_ ) { // if maxsteps == 0, will never call stop(). 00177 this->stop(); 00178 } 00179 } 00180 00181 }