00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include "FunctionGraph.hpp"
00040 #include "GraphCopier.hpp"
00041 #include "../base/AttributeBase.hpp"
00042 #include "ProgramService.hpp"
00043 #include "TaskContext.hpp"
00044 #include "../Service.hpp"
00045
00046 #include "CommandNOP.hpp"
00047 #include "ConditionFalse.hpp"
00048 #include "ConditionTrue.hpp"
00049 #include <boost/graph/copy.hpp>
00050 #include <utility>
00051
00052 namespace RTT {
00053 using namespace detail;
00054 using namespace boost;
00055 using namespace std;
00056
00057
00058
00059 FunctionGraph::FunctionGraph(const std::string& _name, bool unload_on_stop)
00060 : myName(_name), retn(0), pausing(false), mstep(false), munload_on_stop(unload_on_stop)
00061 {
00062
00063 startv = add_vertex( program );
00064 put(vertex_exec, program, startv, VertexNode::normal_node );
00065 exitv = add_vertex( program );
00066 put(vertex_exec, program, exitv, VertexNode::normal_node);
00067 }
00068
00069 FunctionGraph::FunctionGraph( const FunctionGraph& orig )
00070 : program( orig.getGraph() ), myName( orig.getName() )
00071 {
00072
00073 graph_traits<Graph>::vertex_iterator v1,v2, it;
00074 tie(v1,v2) = vertices(program);
00075 for ( it=v1; it != v2; ++it)
00076 if ( get( vertex_exec, program, *it) == VertexNode::func_start_node )
00077 break;
00078 startv = *v1;
00079 for ( it=v1; it != v2; ++it)
00080 if ( get( vertex_exec, program, *it) == VertexNode::func_exit_node )
00081 break;
00082 exitv = *v1;
00083
00084
00085 std::vector<AttributeBase*> argsvect = orig.getArguments();
00086 std::vector<AttributeBase*>::iterator ita = argsvect.begin();
00087 for ( ; ita != argsvect.end(); ++ita)
00088 this->args.push_back( (*ita)->clone() );
00089 if (orig.retn)
00090 retn = orig.retn->clone();
00091 this->finish();
00092 }
00093
00094 void FunctionGraph::finish()
00095 {
00096 put(vertex_exec, program, startv, VertexNode::func_start_node );
00097 put(vertex_exec, program, exitv, VertexNode::func_exit_node);
00098
00099
00100
00101
00102 property_map<Graph, vertex_index_t>::type
00103 index = get(vertex_index, program);
00104
00105
00106
00107 graph_traits<Graph>::vertex_iterator vi, vend;
00108 graph_traits<Graph>::vertices_size_type cnt = 0;
00109 for(tie(vi,vend) = vertices(program); vi != vend; ++vi)
00110 put(index, *vi, cnt++);
00111 this->reset();
00112 }
00113
00114 FunctionGraph::~FunctionGraph()
00115 {
00116 log(Debug) << "Destroying program '" << getName() << "'" <<endlog();
00117 if ( this->isLoaded() ){
00118 getEngine()->removeFunction(this);
00119 }
00120 std::vector<AttributeBase*>::iterator it = args.begin();
00121 for ( ; it != args.end(); ++it)
00122 delete *it;
00123
00124 }
00125
00126 void FunctionGraph::setProgramService(Service::shared_ptr myservice)
00127 {
00128 context = myservice;
00129 }
00130
00131 void FunctionGraph::setUnloadOnStop(bool unload_on_stop)
00132 {
00133 munload_on_stop = unload_on_stop;
00134 }
00135
00136 void FunctionGraph::loading()
00137 {
00138
00139 if (munload_on_stop)
00140 this->start();
00141 }
00142
00143 void FunctionGraph::unloading()
00144 {
00145
00146
00147
00148 if ( !context )
00149 return;
00150
00151
00152 if (context->getParent() ) {
00153 context->getParent()->removeService(context->getName());
00154 }
00155 context.reset();
00156 }
00157
00158
00159 bool FunctionGraph::start()
00160 {
00161 if ( !isLoaded() )
00162 return false;
00163 if ( pStatus == Status::stopped ) {
00164 this->reset();
00165 }
00166 if ( pStatus == Status::stopped || pStatus == Status::paused) {
00167 pStatus = Status::running;
00168 return true;
00169 }
00170 return false;
00171 }
00172
00173 bool FunctionGraph::pause()
00174 {
00175 if ( isLoaded() ) {
00176 if ( pStatus == Status::stopped ) {
00177 this->reset();
00178 }
00179 pausing = true;
00180 return true;
00181 }
00182 return false;
00183 }
00184
00185 bool FunctionGraph::step()
00186 {
00187 if ( isLoaded() && (pStatus == Status::paused) && mstep == false) {
00188 mstep = true;
00189 return true;
00190 }
00191 return false;
00192 }
00193
00194 bool FunctionGraph::stepDone() const
00195 {
00196 return mstep == false;
00197 }
00198
00199 bool FunctionGraph::execute()
00200 {
00201 if (pausing) {
00202 pStatus = Status::paused;
00203 pausing = false;
00204 return true;
00205 }
00206 switch (pStatus) {
00207 case Status::running:
00208 this->executeUntil();
00209 return true;
00210 break;
00211 case Status::paused:
00212 if (mstep) {
00213 mstep = false;
00214 this->executeStep();
00215 return true;
00216 } else
00217 return true;
00218 break;
00219 case Status::error:
00220 case Status::unknown:
00221 case Status::stopped:
00222 return !munload_on_stop;
00223 break;
00224 }
00225 return false;
00226 }
00227
00228
00229 bool FunctionGraph::executeUntil()
00230 {
00231 graph_traits<Graph>::out_edge_iterator ei, ei_end;
00232
00233 boost::property_map<Graph, vertex_command_t>::type
00234 cmap = get(vertex_command, program);
00235 boost::property_map<Graph, edge_condition_t>::type
00236 emap = get(edge_condition, program);
00237
00238 do {
00239
00240
00241
00242
00243 if ( previous != current )
00244 {
00245 for ( tie(ei, ei_end) = boost::out_edges( current, program ); ei != ei_end; ++ei)
00246 emap[*ei].reset();
00247 try {
00248 cmap[current].startExecution();
00249 } catch(...) {
00250 pStatus = Status::error;
00251 return false;
00252 }
00253 }
00254
00255
00256 previous = current;
00257
00258 try {
00259 cmap[current].execute();
00260 } catch(...) {
00261 pStatus = Status::error;
00262 return false;
00263 }
00264
00265
00266 if ( cmap[current].isValid() ) {
00267 for ( tie(ei, ei_end) = boost::out_edges( current, program ); ei != ei_end; ++ei) {
00268 try {
00269 if ( emap[*ei].evaluate() ) {
00270 current = boost::target(*ei, program);
00271
00272
00273 break;
00274 }
00275 } catch(...) {
00276 pStatus = Status::error;
00277 return false;
00278 }
00279 }
00280 }
00281 } while ( previous != current && pStatus == Status::running && !pausing);
00282
00283
00284 if (current == exitv)
00285 this->stop();
00286 return true;
00287 }
00288
00289 bool FunctionGraph::executeStep()
00290 {
00291 graph_traits<Graph>::out_edge_iterator ei, ei_end;
00292
00293 boost::property_map<Graph, vertex_command_t>::type
00294 cmap = get(vertex_command, program);
00295 boost::property_map<Graph, edge_condition_t>::type
00296 emap = get(edge_condition, program);
00297
00298
00299 if ( previous != current )
00300 {
00301 for ( tie(ei, ei_end) = boost::out_edges( current, program ); ei != ei_end; ++ei)
00302 emap[*ei].reset();
00303 try {
00304 cmap[current].startExecution();
00305 } catch(...) {
00306 pStatus = Status::error;
00307 return false;
00308 }
00309 previous = current;
00310 }
00311
00312
00313 try {
00314 cmap[current].execute();
00315 } catch(...) {
00316 pStatus = Status::error;
00317 return false;
00318 }
00319
00320
00321 if ( cmap[current].isValid() ) {
00322 for ( tie(ei, ei_end) = boost::out_edges( current, program ); ei != ei_end; ++ei) {
00323 try {
00324 if ( emap[*ei].evaluate() ) {
00325 current = boost::target(*ei, program);
00326 if (current == exitv)
00327 this->stop();
00328
00329
00330 return true;
00331 }
00332 } catch(...) {
00333 pStatus = Status::error;
00334 return false;
00335 }
00336 }
00337 }
00338
00339 if (current == exitv)
00340 this->stop();
00341 return true;
00342 }
00343
00344 void FunctionGraph::reset() {
00345 current = startv;
00346 previous = exitv;
00347 this->stop();
00348 }
00349
00350 bool FunctionGraph::stop()
00351 {
00352
00353 pStatus = Status::stopped;
00354 return true;
00355 }
00356
00357 const std::string& FunctionGraph::getName() const
00358 {
00359 return myName;
00360 }
00361
00362 void FunctionGraph::setName(const std::string& name)
00363 {
00364 myName = name;
00365 }
00366
00367 std::string FunctionGraph::getText() const
00368 {
00369 return _text;
00370 }
00371
00372 void FunctionGraph::setText(const std::string& text)
00373 {
00374 _text = text;
00375 }
00376
00377 int FunctionGraph::getLineNumber() const
00378 {
00379 return get(vertex_command, program)[current].getLineNumber();
00380 }
00381
00382 FunctionGraph* FunctionGraph::copy( std::map<const DataSourceBase*, DataSourceBase*>& replacementdss ) const
00383 {
00384 typedef boost::property_map<Graph, vertex_index_t>::const_type indexmap_t;
00385 typedef boost::graph_traits<Graph>::vertex_descriptor vd_t;
00386 typedef std::vector<vd_t> o2cvect_t;
00387 typedef boost::iterator_property_map<o2cvect_t::iterator, indexmap_t, vd_t, vd_t&> o2cmap_t;
00388 FunctionGraph* ret = new FunctionGraph( getName(), munload_on_stop );
00389
00390
00391 remove_vertex( ret->startv, ret->program );
00392 remove_vertex( ret->exitv, ret->program );
00393
00394 indexmap_t indexmap = get( vertex_index, program );
00395
00396 o2cvect_t o2cvect( num_vertices( program ) );
00397 o2cmap_t o2cmap( o2cvect.begin(), indexmap );
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407 for (unsigned int i=0; i < args.size(); ++i)
00408 ret->addArgument( args[i]->copy( replacementdss, false ) );
00409 if (retn)
00410 ret->setResult( retn->copy(replacementdss, false) );
00411
00412 boost::copy_graph( program, ret->program,
00413 boost::vertex_copy( GraphVertexCopier( program, ret->program, replacementdss ) ).
00414 edge_copy( GraphEdgeCopier( program, ret->program, replacementdss ) ).
00415 orig_to_copy( o2cmap ) );
00416
00417 ret->startv = o2cmap[startv];
00418 ret->exitv = o2cmap[exitv];
00419 ret->current = o2cmap[current];
00420 ret->previous = o2cmap[previous];
00421
00422
00423 ret->finish();
00424
00425
00426
00427
00428 return ret;
00429 }
00430
00431 FunctionGraph* FunctionGraph::clone() const
00432 {
00433 return new FunctionGraph(*this);
00434 }
00435
00436 void FunctionGraph::debugPrintout() const {
00437 #if 0
00438 graph_traits<Graph>::vertex_iterator v,vend;
00439 tie(v,vend) = vertices(program);
00440 boost::property_map<Graph, vertex_command_t>::const_type
00441 cmap = get(vertex_command, program);
00442 boost::property_map<Graph, vertex_index_t>::const_type
00443 imap = get(vertex_index, program);
00444 std::cerr << "program " << getName() << std::endl;
00445 std::cerr << " number of vertices: " << boost::num_vertices(program) << std::endl;
00446 for ( ; v != vend; ++v )
00447 {
00448 int index = get( imap, *v );
00449 ActionInterface* cmd = get( cmap, *v ).getCommand();
00450 if ( cmd )
00451 std::cerr << " " << index << " " << typeid( *cmd ).name() << std::endl;
00452 else
00453 std::cerr << " " << index << " (null)" << std::endl;
00454 }
00455 #endif
00456 }
00457
00458 void FunctionGraph::clearArguments() {
00459 for (std::vector<AttributeBase*>::iterator it = args.begin(); it != args.end(); ++it)
00460 delete *it;
00461 args.clear();
00462 }
00463
00464 }
00465