Orocos Real-Time Toolkit
2.5.0
|
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