Orocos Real-Time Toolkit  2.5.0
TaskCore.cpp
00001 /***************************************************************************
00002   tag: FMTC  Tue Mar 11 21:49:25 CET 2008  TaskCore.cpp
00003 
00004                         TaskCore.cpp -  description
00005                            -------------------
00006     begin                : Tue March 11 2008
00007     copyright            : (C) 2008 FMTC
00008     email                : peter.soetens@fmtc.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 "TaskCore.hpp"
00041 #include "../ExecutionEngine.hpp"
00042 #include "ActivityInterface.hpp"
00043 #include "Logger.hpp"
00044 
00045 namespace RTT {
00046     using namespace detail;
00047 
00048     using namespace std;
00049 
00050     TaskCore::TaskCore(TaskState initial_state /*= Stopped*/ )
00051         :  ee( new ExecutionEngine(this) )
00052            ,mTaskState(initial_state)
00053            ,mInitialState(initial_state)
00054            ,mTargetState(initial_state)
00055     {
00056     }
00057 
00058     TaskCore::TaskCore( ExecutionEngine* parent, TaskState initial_state /*= Stopped*/  )
00059         :  ee( parent )
00060            ,mTaskState(initial_state)
00061            ,mInitialState(initial_state)
00062            ,mTargetState(initial_state)
00063     {
00064         parent->addChild( this );
00065     }
00066 
00067 
00068     TaskCore::~TaskCore()
00069     {
00070         if ( ee->getParent() == this ) {
00071             delete ee;
00072         } else {
00073             ee->removeChild(this);
00074         }
00075         // Note: calling cleanup() here has no use or even dangerous, as
00076         // cleanupHook() is a virtual function and the user code is already
00077         // destroyed. The user's subclass is responsible to make this state
00078         // transition in its destructor if required.
00079     }
00080 
00081     TaskCore::TaskState TaskCore::getTaskState() const {
00082         return mTaskState;
00083     }
00084 
00085     TaskCore::TaskState TaskCore::getTargetState() const {
00086         return mTargetState;
00087     }
00088 
00089     bool TaskCore::update()
00090     {
00091         if ( !this->engine()->getActivity() )
00092             return false;
00093         return this->engine()->getActivity()->execute();
00094     }
00095 
00096     bool TaskCore::trigger()
00097     {
00098         if ( !this->engine()->getActivity() )
00099             return false;
00100         return this->engine()->getActivity()->trigger();
00101     }
00102 
00103     bool TaskCore::configure() {
00104         if ( mTaskState == Stopped || mTaskState == PreOperational) {
00105             try {
00106                 mTargetState = Stopped;
00107                 if (configureHook() ) {
00108                     mTaskState = Stopped;
00109                     return true;
00110                 } else {
00111                     mTargetState = mTaskState = PreOperational;
00112                     return false;
00113                 }
00114             } catch(std::exception const& e) {
00115                 log(Error) << "in configure(): switching to exception state because of unhandled exception" << endlog();
00116                 log(Error) << "  " << e.what() << endlog();
00117                 exception();
00118             } catch(...) {
00119                 log(Error) << "in configure(): switching to exception state because of unhandled exception" << endlog();
00120                 exception();
00121             }
00122         }
00123         return false; // no configure when running.
00124     }
00125 
00126     bool TaskCore::cleanup() {
00127         if ( mTaskState == Stopped ) {
00128             try {
00129                 mTargetState = PreOperational;
00130                 cleanupHook();
00131                 mTaskState = PreOperational;
00132                 return true;
00133             } catch(std::exception const& e) {
00134                 log(Error) << "in cleanup(): switching to exception state because of unhandled exception" << endlog();
00135                 log(Error) << "  " << e.what() << endlog();
00136                 exception();
00137             } catch (...) {
00138                 log(Error) << "in cleanup(): switching to exception state because of unhandled exception" << endlog();
00139                 exception();
00140             }
00141         }
00142         return false; // no cleanup when running or not configured.
00143     }
00144 
00145     void TaskCore::fatal() {
00146         mTargetState = mTaskState = FatalError;
00147         if ( engine()->getActivity() )
00148             engine()->getActivity()->stop();
00149     }
00150 
00151     void TaskCore::error() {
00152         // detects error() from within start():
00153         if (mTargetState < Running)
00154             return;
00155         mTargetState = mTaskState = RunTimeError;
00156     }
00157 
00158     void TaskCore::exception() {
00159         //log(Error) <<"Exception happend in TaskCore."<<endlog();
00160         TaskState copy = mTaskState;
00161         mTargetState = mTaskState = Exception;
00162         try {
00163             if ( copy >= Running ) {
00164                 stopHook();
00165             }
00166             if ( copy >= Stopped ) {
00167                 cleanupHook();
00168             }
00169             exceptionHook();
00170         } catch(std::exception const& e) {
00171             log(RTT::Error) << "stopHook(), cleanupHook() and/or exceptionHook() raised " << e.what() << ", going into Fatal" << endlog();
00172             fatal();
00173         }
00174         catch (...) {
00175             log(Error) << "stopHook(), cleanupHook() and/or exceptionHook() raised an exception, going into Fatal" << endlog();
00176             fatal();
00177         }
00178     }
00179 
00180     bool TaskCore::recover() {
00181         if ( mTaskState == Exception ) {
00182             mTargetState = mTaskState = mInitialState;
00183             return true;
00184         }
00185         if (mTaskState == RunTimeError ) {
00186             mTargetState = mTaskState = Running;
00187             return true;
00188         }
00189         return false;
00190     }
00191 
00192     bool TaskCore::start() {
00193         if ( mTaskState == Stopped ) {
00194             try {
00195                 mTargetState = Running;
00196                 if ( startHook() ) {
00197                     mTaskState = Running;
00198                     trigger(); // triggers updateHook() in case of non periodic!
00199                     return true;
00200                 }
00201                 mTargetState = Stopped;
00202             } catch(std::exception const& e) {
00203                 log(Error) << "in start(): switching to exception state because of unhandled exception" << endlog();
00204                 log(Error) << "  " << e.what() << endlog();
00205                 exception();
00206             } catch (...) {
00207                 log(Error) << "in start(): switching to exception state because of unhandled exception" << endlog();
00208                 exception();
00209             }
00210         }
00211         return false;
00212     }
00213 
00214     bool TaskCore::stop() {
00215         TaskState orig = mTaskState;
00216         if ( mTaskState >= Running ) {
00217             try {
00218                 mTargetState = Stopped;
00219                 if ( engine()->stopTask(this) ) {
00220                     stopHook();
00221                     mTaskState = Stopped;
00222                     return true;
00223                 } else {
00224                     mTaskState = orig;
00225                     mTargetState = orig;
00226                 }
00227             } catch(std::exception const& e) {
00228                 log(Error) << "in stop(): switching to exception state because of unhandled exception" << endlog();
00229                 log(Error) << "  " << e.what() << endlog();
00230                 exception();
00231             } catch (...) {
00232                 log(Error) << "in stop(): switching to exception state because of unhandled exception" << endlog();
00233                 exception();
00234             }
00235         }
00236         return false;
00237     }
00238 
00239     bool TaskCore::activate() {
00240         this->engine() && this->engine()->getActivity() && this->engine()->getActivity()->start();
00241         return isActive();
00242     }
00243 
00244     void TaskCore::cleanupHook() {
00245     }
00246 
00247     bool TaskCore::isRunning() const {
00248         return mTaskState >= Running;
00249     }
00250 
00251     bool TaskCore::isConfigured() const {
00252         return mTaskState >= Stopped;
00253     }
00254 
00255     bool TaskCore::inFatalError() const {
00256         return mTaskState == FatalError;
00257     }
00258 
00259     bool TaskCore::inException() const {
00260         return mTaskState == Exception;
00261     }
00262 
00263     bool TaskCore::inRunTimeError() const {
00264         return mTaskState == RunTimeError;
00265     }
00266 
00267     bool TaskCore::isActive() const
00268     {
00269         return this->engine() && this->engine()->getActivity() && this->engine()->getActivity()->isActive();
00270     }
00271 
00272     Seconds TaskCore::getPeriod() const
00273     {
00274         return this->engine()->getActivity() ? this->engine()->getActivity()->getPeriod() : -1.0;
00275     }
00276 
00277     bool TaskCore::setPeriod(Seconds s)
00278     {
00279         return this->engine()->getActivity() ? this->engine()->getActivity()->setPeriod(s) : false;
00280     }
00281 
00282     unsigned TaskCore::getCpuAffinity() const
00283     {
00284         return this->engine()->getActivity() ? this->engine()->getActivity()->getCpuAffinity() : ~0;
00285     }
00286 
00287     bool TaskCore::setCpuAffinity(unsigned cpu)
00288     {
00289         return this->engine()->getActivity() ? this->engine()->getActivity()->setCpuAffinity(cpu) : false;
00290     }
00291 
00292     bool TaskCore::configureHook() {
00293         return true;
00294     }
00295 
00296     bool TaskCore::startHook()
00297     {
00298         return true;
00299     }
00300 
00301     void TaskCore::errorHook() {
00302     }
00303 
00304     void TaskCore::prepareUpdateHook() {
00305     }
00306 
00307     void TaskCore::updateHook()
00308     {
00309     }
00310 
00311     bool TaskCore::breakUpdateHook()
00312     {
00313         return true;
00314     }
00315 
00316     void TaskCore::exceptionHook() {
00317     }
00318 
00319     void TaskCore::stopHook()
00320     {
00321     }
00322 
00323     void TaskCore::setExecutionEngine(ExecutionEngine* engine) {
00324         if ( ee == engine )
00325             return;
00326         // cleanup:
00327         if ( ee->getParent() == this )
00328             delete ee;
00329         else
00330             ee->removeChild(this);
00331         // set new:
00332         if ( engine ) {
00333             this->ee = engine;
00334             engine->addChild(this);
00335         } else {
00336             this->ee = new ExecutionEngine(this);
00337         }
00338     }
00339 
00340 }
00341