Orocos Real-Time Toolkit  2.6.0
SimulationThread.cpp
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 }