| The Gaudi Framework v32r1 (f65d50dc)

PrecedenceRulesGraph.cpp
Go to the documentation of this file.
1 #include "PrecedenceRulesGraph.h"
2 #include "Visitors/Promoters.h"
3
4 #include "GaudiKernel/DataHandleFinder.h"
5
6 #include <boost/property_map/transform_value_property_map.hpp>
7 #include <fstream>
8
9 #define ON_DEBUG if ( msgLevel( MSG::DEBUG ) )
10 #define ON_VERBOSE if ( msgLevel( MSG::VERBOSE ) )
11
12 namespace {
13 //---------------------------------------------------------------------------
15 const char* stateToString( const int& stateId ) {
16 switch ( stateId ) {
17 case 0:
18 return "FALSE";
19 case 1:
20 return "TRUE";
21 default:
22 return "UNDEFINED";
23 }
24 }
25 } // namespace
26
27 namespace concurrency {
28
29 //---------------------------------------------------------------------------
30 void DecisionNode::addParentNode( DecisionNode* node ) {
31
32 if ( std::find( m_parents.begin(), m_parents.end(), node ) == m_parents.end() ) m_parents.push_back( node );
33 }
34
35 //--------------------------------------------------------------------------
36 void DecisionNode::addDaughterNode( ControlFlowNode* node ) {
37
38 if ( std::find( m_children.begin(), m_children.end(), node ) == m_children.end() ) m_children.push_back( node );
39 }
40
41 //---------------------------------------------------------------------------
42 void DecisionNode::printState( std::stringstream& output, EventSlot& slot,
43 const unsigned int& recursionLevel ) const {
44
45 auto& node_decisions = slot.controlFlowState;
46 output << std::string( recursionLevel, ' ' ) << m_nodeName << " (" << m_nodeIndex << ")"
47 << ", w/ decision: " << stateToString( node_decisions[m_nodeIndex] ) << "(" << node_decisions[m_nodeIndex]
48 << ")" << std::endl;
49
50 for ( auto daughter : m_children ) daughter->printState( output, slot, recursionLevel + 2 );
51 }
52
53 //---------------------------------------------------------------------------
54 bool DecisionNode::accept( IGraphVisitor& visitor ) {
55
56 if ( visitor.visitEnter( *this ) ) {
57 // try to aggregate a decision
58 bool result = visitor.visit( *this );
59 return !result;
60 }
61
62 return false; // visitor was rejected (since the decision node has an aggregated decision already)
63 }
64
65 //---------------------------------------------------------------------------
66 void AlgorithmNode::printState( std::stringstream& output, EventSlot& slot,
67 const unsigned int& recursionLevel ) const {
68
69 auto& node_decisions = slot.controlFlowState;
70 auto& states = slot.algsStates;
71 std::string indent( recursionLevel, ' ' );
72 output << indent << m_nodeName << " (" << m_nodeIndex << ")"
73 << ", w/ decision: " << stateToString( node_decisions[m_nodeIndex] ) << "(" << node_decisions[m_nodeIndex]
74 << ")"
75 << ", in state: " << states[m_algoIndex] << std::endl;
76
77 // In a stall, CONTROLREADY nodes are interesting
78 if ( states[m_algoIndex] == AlgsExecutionStates::State::CONTROLREADY ) {
79
80 // Check all data dependencies
81 output << indent << "========" << std::endl;
82 for ( auto dataNode : this->getInputDataNodes() ) {
83
84 // Was the data produced?
85 ConditionNode* castNode = dynamic_cast<ConditionNode*>( dataNode );
86 DataReadyPromoter visitor( slot, {} );
87 bool wasProduced = false;
88 if ( castNode ) {
89 // ConditionNodes always request data on visit()
90 // Instead take the opposite of visitEnter(), since you may not enter if it already exists
91 wasProduced = !visitor.visitEnter( *castNode );
92 } else {
93 // For DataNodes, the check is done in visit()
94 wasProduced = visitor.visit( *dataNode );
95 }
96
97 // Print out states of producer algs if data is missing
98 if ( !wasProduced ) {
99
100 // Say if it's conditions data or not
101 if ( castNode )
102 output << indent << "missing conditions data: " << dataNode->getPath() << std::endl;
103 else
104 output << indent << "missing data: " << dataNode->getPath() << std::endl;
105
106 // Find out if the algorithm needs it because of a tool
107 DataHandleFinder finder( dataNode->getPath() );
108 this->getAlgorithm()->acceptDHVisitor( &finder );
109 if ( finder.holderNames().size() > 1 ) {
110 output << indent << "required by tool:";
111 for ( auto const& holderName : finder.holderNames() ) {
112 if ( holderName != this->getNodeName() ) output << " " << holderName;
113 }
114 output << std::endl;
115 }
116
117 // State which algs produce this data
118 output << indent << "can be produced by alg(s): ";
119 for ( auto algoNode : dataNode->getProducers() ) {
120 output << "( " << algoNode->getNodeName() << " in state: " << states[algoNode->getAlgoIndex()] << " ) ";
121 }
122 output << std::endl;
123
124 // See where data is available (ignore conditions, since these are top-level)
125 if ( !castNode ) {
126 std::vector<EventSlot>* testSubSlots = &slot.allSubSlots;
127 auto* subSlotMap = &slot.subSlotsByNode;
128
129 // Examine the top-level slot if you did not start there
130 if ( slot.parentSlot ) {
131 visitor.m_slot = slot.parentSlot;
132 testSubSlots = &slot.parentSlot->allSubSlots;
133 subSlotMap = &slot.parentSlot->subSlotsByNode;
134 if ( visitor.visit( *dataNode ) ) {
135 output << indent << "data is available at whole-event level" << std::endl;
136 }
137 }
138
139 // Examine all sub slots, grouped by entry point
140 for ( auto& pair : *subSlotMap ) {
141 if ( pair.second.size() > 0 ) {
142 bool madeLine = false;
143
144 // Loop over the slots for this entry point
145 for ( int slotIndex : pair.second ) {
146
147 EventSlot* subSlot = &testSubSlots->at( slotIndex );
148 visitor.m_slot = subSlot;
149 if ( visitor.visit( *dataNode ) ) {
150
151 if ( !madeLine ) {
152 // Only mention this set of sub-slots at all if one has the data
153 output << indent << "data is available in sub-slot(s) ";
154 madeLine = true;
155 }
156 output << slotIndex << ", ";
157 }
158 }
159 if ( madeLine ) { output << "entered from " << pair.first << std::endl; }
160 }
161 }
162 }
163 }
164 }
165 output << indent << "========" << std::endl;
166 }
167 }
168
169 //---------------------------------------------------------------------------
170 bool AlgorithmNode::accept( IGraphVisitor& visitor ) {
171
172 if ( visitor.visitEnter( *this ) ) {
173 visitor.visit( *this );
174 return true; // visitor was accepted to promote the algorithm
175 }
176
177 return false; // visitor was rejected (since the algorithm already produced a decision)
178 }
179
180 //---------------------------------------------------------------------------
181 void AlgorithmNode::addParentNode( DecisionNode* node ) {
182
183 if ( std::find( m_parents.begin(), m_parents.end(), node ) == m_parents.end() ) m_parents.push_back( node );
184 }
185
186 //---------------------------------------------------------------------------
187 void AlgorithmNode::addOutputDataNode( DataNode* node ) {
188
189 if ( std::find( m_outputs.begin(), m_outputs.end(), node ) == m_outputs.end() ) m_outputs.push_back( node );
190 }
191
192 //---------------------------------------------------------------------------
193 void AlgorithmNode::addInputDataNode( DataNode* node ) {
194
195 if ( std::find( m_inputs.begin(), m_inputs.end(), node ) == m_inputs.end() ) m_inputs.push_back( node );
196 }
197
198 //---------------------------------------------------------------------------
199 StatusCode PrecedenceRulesGraph::initialize() {
200 if ( serviceLocator()->existsService( "CondSvc" ) ) {
201 SmartIF<ICondSvc> condSvc{serviceLocator()->service( "CondSvc" )};
202 if ( condSvc.isValid() ) {
203 info() << "CondSvc found. DF precedence rules will be augmented with 'Conditions'" << endmsg;
204 m_conditionsRealmEnabled = true;
205 }
206 }
207
208 // Detach condition algorithms from the CF realm
209 if ( m_conditionsRealmEnabled ) {
210 SmartIF<ICondSvc> condSvc{serviceLocator()->service( "CondSvc", false )};
211 auto& condAlgs = condSvc->condAlgs();
212 for ( const auto algo : condAlgs ) {
213 auto itA = m_algoNameToAlgoNodeMap.find( algo->name() );
214 if ( itA != m_algoNameToAlgoNodeMap.end() ) {
215 concurrency::AlgorithmNode* algoNode = itA->second.get();
216 debug() << "Detaching condition algorithm '" << algo->name() << "' from the CF realm.." << endmsg;
217 for ( auto parent : algoNode->getParentDecisionHubs() ) {
218 parent->m_children.erase( std::remove( parent->m_children.begin(), parent->m_children.end(), algoNode ),
219 parent->m_children.end() );
220 // clean up also auxiliary BGL-based graph of precedence rules
221 if ( m_enableAnalysis )
222 boost::remove_edge( node( algoNode->getNodeName() ), node( parent->getNodeName() ), m_PRGraph );
223 }
224 algoNode->m_parents.clear();
225
226 } else {
227 warning() << "Algorithm '" << algo->name() << "' is not registered in the graph" << endmsg;
228 }
229 }
230 }
231
232 StatusCode sc = buildDataDependenciesRealm();
233
234 if ( !sc.isSuccess() ) error() << "Could not build the data dependency realm." << endmsg;
235
236 ON_DEBUG debug() << dumpDataFlow() << endmsg;
237
238 return sc;
239 }
240
241 //---------------------------------------------------------------------------
242 void PrecedenceRulesGraph::registerIODataObjects( const Gaudi::Algorithm* algo ) {
243
244 const std::string& algoName = algo->name();
245
246 m_algoNameToAlgoInputsMap[algoName] = algo->inputDataObjs();
247 m_algoNameToAlgoOutputsMap[algoName] = algo->outputDataObjs();
248
249 ON_VERBOSE {
250 verbose() << " Inputs of " << algoName << ": ";
251 for ( auto tag : algo->inputDataObjs() ) verbose() << tag << " | ";
252 verbose() << endmsg;
253
254 verbose() << " Outputs of " << algoName << ": ";
255 for ( auto tag : algo->outputDataObjs() ) verbose() << tag << " | ";
256 verbose() << endmsg;
257 }
258 }
259
260 //---------------------------------------------------------------------------
261 StatusCode PrecedenceRulesGraph::buildDataDependenciesRealm() {
262
263 StatusCode global_sc( StatusCode::SUCCESS, true );
264
265 // Production of DataNodes by AlgorithmNodes (DataNodes are created here)
266 for ( auto& algo : m_algoNameToAlgoNodeMap ) {
267
268 auto& outputs = m_algoNameToAlgoOutputsMap[algo.first];
269 for ( auto output : outputs ) {
270 const auto sc = addDataNode( output );
271 if ( !sc.isSuccess() ) {
272 error() << "Extra producer (" << algo.first << ") for DataObject @ " << output
273 << " has been detected: this is not allowed." << endmsg;
274 global_sc = sc;
275 }
276 auto dataNode = getDataNode( output );
277 dataNode->addProducerNode( algo.second.get() );
278 algo.second->addOutputDataNode( dataNode );
279
280 // Mirror the action above in the BGL-based graph
281 if ( m_enableAnalysis )
282 boost::add_edge( node( algo.second->getNodeName() ), node( output.fullKey() ), m_PRGraph );
283 }
284 }
285
286 // Consumption of DataNodes by AlgorithmNodes
287 for ( auto& algo : m_algoNameToAlgoNodeMap ) {
288
289 for ( auto input : m_algoNameToAlgoInputsMap[algo.first] ) {
290
291 auto itP = m_dataPathToDataNodeMap.find( input );
292
293 DataNode* dataNode = ( itP != m_dataPathToDataNodeMap.end() ? getDataNode( input ) : nullptr );
294 if ( dataNode ) {
295 dataNode->addConsumerNode( algo.second.get() );
296 algo.second->addInputDataNode( dataNode );
297
298 // Mirror the action above in the BGL-based graph
299 if ( m_enableAnalysis )
300 boost::add_edge( node( input.fullKey() ), node( algo.second->getNodeName() ), m_PRGraph );
301 }
302 }
303 }
304
305 return global_sc;
306 }
307
308 //---------------------------------------------------------------------------
309 StatusCode PrecedenceRulesGraph::addAlgorithmNode( Gaudi::Algorithm* algo, const std::string& parentName,
310 bool inverted, bool allPass ) {
311
312 StatusCode sc = StatusCode::SUCCESS;
313
315
316 auto& algoName = algo->name();
317
318 concurrency::AlgorithmNode* algoNode;
319
320 auto itA = m_algoNameToAlgoNodeMap.find( algoName );
321 if ( itA != m_algoNameToAlgoNodeMap.end() ) {
322 algoNode = itA->second.get();
323 } else {
324 auto r = m_algoNameToAlgoNodeMap.emplace(
325 algoName, std::make_unique<concurrency::AlgorithmNode>( *this, algo, m_nodeCounter, m_algoCounter, inverted,
326 allPass ) );
327 algoNode = r.first->second.get();
328
329 // Mirror AlgorithmNode in the BGL-based graph
330 if ( m_enableAnalysis ) {
331 boost::add_vertex( AlgoProps( algo, m_nodeCounter, m_algoCounter, inverted, allPass ), m_PRGraph );
332 }
333 ++m_nodeCounter;
334 ++m_algoCounter;
335 ON_VERBOSE verbose() << "AlgorithmNode '" << algoName << "' added @ " << algoNode << endmsg;
336
337 registerIODataObjects( algo );
338 }
339
341 auto itP = m_decisionNameToDecisionHubMap.find( parentName );
342 if ( itP != m_decisionNameToDecisionHubMap.end() ) {
343 auto parentNode = itP->second.get();
344
345 parentNode->addDaughterNode( algoNode );
346 algoNode->addParentNode( parentNode );
347
348 // Mirror algorithm to CF parent relationship in the BGL-based graph
349 if ( m_enableAnalysis ) boost::add_edge( node( algo->name() ), node( parentName ), m_PRGraph );
350
351 ON_VERBOSE verbose() << "Attached AlgorithmNode '" << algo->name() << "' to parent DecisionNode '" << parentName
352 << "'" << endmsg;
353 } else {
354 sc = StatusCode::FAILURE;
355 error() << "Parent DecisionNode '" << parentName << "' was not found" << endmsg;
356 }
357
358 return sc;
359 }
360
361 //---------------------------------------------------------------------------
362 StatusCode PrecedenceRulesGraph::addDataNode( const DataObjID& dataPath ) {
363
364 auto itD = m_dataPathToDataNodeMap.find( dataPath );
365 if ( itD != m_dataPathToDataNodeMap.end() ) return StatusCode::SUCCESS;
366
367 std::unique_ptr<concurrency::DataNode> dataNode;
368 if ( !m_conditionsRealmEnabled ) {
369 dataNode = std::make_unique<concurrency::DataNode>( *this, dataPath );
370 ON_VERBOSE verbose() << " DataNode " << dataPath << " added @ " << dataNode.get() << endmsg;
371 // Mirror the action above in the BGL-based graph
372 if ( m_enableAnalysis ) boost::add_vertex( DataProps( dataPath ), m_PRGraph );
373 } else {
374 SmartIF<ICondSvc> condSvc{serviceLocator()->service( "CondSvc", false )};
375 if ( condSvc->isRegistered( dataPath ) ) {
376 dataNode = std::make_unique<concurrency::ConditionNode>( *this, dataPath, condSvc );
377 ON_VERBOSE verbose() << " ConditionNode " << dataPath << " added @ " << dataNode.get() << endmsg;
378 // Mirror the action above in the BGL-based graph
379 if ( m_enableAnalysis ) boost::add_vertex( CondDataProps( dataPath ), m_PRGraph );
380 } else {
381 dataNode = std::make_unique<concurrency::DataNode>( *this, dataPath );
382 ON_VERBOSE verbose() << " DataNode " << dataPath << " added @ " << dataNode.get() << endmsg;
383 // Mirror the action above in the BGL-based graph
384 if ( m_enableAnalysis ) boost::add_vertex( DataProps( dataPath ), m_PRGraph );
385 }
386 }
387 m_dataPathToDataNodeMap.emplace( dataPath, std::move( dataNode ) );
388 return StatusCode::SUCCESS;
389 }
390
391 //---------------------------------------------------------------------------
392 StatusCode PrecedenceRulesGraph::addDecisionHubNode( Gaudi::Algorithm* decisionHubAlgo, const std::string& parentName,
393 Concurrent modeConcurrent, PromptDecision modePromptDecision,
394 ModeOr modeOR, AllPass allPass, Inverted isInverted ) {
395
396 StatusCode sc = StatusCode::SUCCESS;
397
399
400 auto& decisionHubName = decisionHubAlgo->name();
401
402 auto itA = m_decisionNameToDecisionHubMap.find( decisionHubName );
403 concurrency::DecisionNode* decisionHubNode;
404 if ( itA != m_decisionNameToDecisionHubMap.end() ) {
405 decisionHubNode = itA->second.get();
406 } else {
407 auto r = m_decisionNameToDecisionHubMap.emplace(
408 decisionHubName,
409 std::make_unique<concurrency::DecisionNode>( *this, m_nodeCounter, decisionHubName, modeConcurrent,
410 modePromptDecision, modeOR, allPass, isInverted ) );
411 decisionHubNode = r.first->second.get();
412 // Mirror DecisionNode in the BGL-based graph
413 if ( m_enableAnalysis ) {
414 boost::add_vertex( DecisionHubProps( decisionHubName, m_nodeCounter, modeConcurrent, modePromptDecision, modeOR,
415 allPass, isInverted ),
416 m_PRGraph );
417 }
418
419 ++m_nodeCounter;
420
421 ON_VERBOSE verbose() << "DecisionNode '" << decisionHubName << "' added @ " << decisionHubNode << endmsg;
422 }
423
425 auto itP = m_decisionNameToDecisionHubMap.find( parentName );
426 if ( itP != m_decisionNameToDecisionHubMap.end() ) {
427 auto parentNode = itP->second.get();
428 parentNode->addDaughterNode( decisionHubNode );
429 decisionHubNode->addParentNode( parentNode );
430
431 // Mirror DecisionNode-to-DecisionNode relationship in the BGL-based graph
432 if ( m_enableAnalysis ) boost::add_edge( node( decisionHubName ), node( parentName ), m_PRGraph );
433
434 ON_VERBOSE verbose() << "Attached DecisionNode '" << decisionHubName << "' to parent DecisionNode '" << parentName
435 << "'" << endmsg;
436 } else {
437 sc = StatusCode::FAILURE;
438 error() << "Parent DecisionNode '" << parentName << "' was not found" << endmsg;
439 }
440
441 return sc;
442 }
443
444 //---------------------------------------------------------------------------
445 void PrecedenceRulesGraph::addHeadNode( const std::string& headName, concurrency::Concurrent modeConcurrent,
446 concurrency::PromptDecision modePromptDecision, concurrency::ModeOr modeOR,
447 concurrency::AllPass allPass, concurrency::Inverted isInverted ) {
448
449 auto itH = m_decisionNameToDecisionHubMap.find( headName );
450 if ( itH != m_decisionNameToDecisionHubMap.end() ) {
451 m_headNode = itH->second.get();
452 } else {
453 auto r = m_decisionNameToDecisionHubMap.emplace(
454 headName, std::make_unique<concurrency::DecisionNode>( *this, m_nodeCounter, headName, modeConcurrent,
455 modePromptDecision, modeOR, allPass, isInverted ) );
456 m_headNode = r.first->second.get();
457
458 // Mirror the action above in the BGL-based graph
459 if ( m_enableAnalysis ) {
460 boost::add_vertex( DecisionHubProps( headName, m_nodeCounter, modeConcurrent, modePromptDecision, modeOR,
461 allPass, isInverted ),
462 m_PRGraph );
463 }
464
465 ++m_nodeCounter;
466 }
467 }
468
469 //---------------------------------------------------------------------------
470 PRVertexDesc PrecedenceRulesGraph::node( const std::string& name ) const {
471 auto vp = vertices( m_PRGraph );
472 auto i = std::find_if( vp.first, vp.second, [&]( const PRVertexDesc& v ) {
473 return std::visit( precedence::VertexName(), m_PRGraph[v] ) == name;
474 } );
475 return i != vp.second ? *i : PRVertexDesc{};
476 }
477
478 //---------------------------------------------------------------------------
479 void PrecedenceRulesGraph::accept( IGraphVisitor& visitor ) const {
480 // iterate through Algorithm nodes
481 for ( auto& pr : m_algoNameToAlgoNodeMap ) pr.second->accept( visitor );
482
483 // iterate through DecisionHub nodes
484 for ( auto& pr : m_decisionNameToDecisionHubMap ) pr.second->accept( visitor );
485
486 // iterate through Data [and Conditions] nodes
487 for ( auto& pr : m_dataPathToDataNodeMap ) pr.second->accept( visitor );
488 }
489
490 //---------------------------------------------------------------------------
491 void PrecedenceRulesGraph::rankAlgorithms( IGraphVisitor& ranker ) const {
492
493 info() << "Starting ranking by data outputs .. " << endmsg;
494 for ( auto& pair : m_algoNameToAlgoNodeMap ) {
495 ON_DEBUG debug() << " Ranking " << pair.first << "... " << endmsg;
496 pair.second->accept( ranker );
497 ON_DEBUG debug() << " ... rank of " << pair.first << ": " << pair.second->getRank() << endmsg;
498 }
499 }
500
501 std::string PrecedenceRulesGraph::dumpControlFlow() const {
502 std::ostringstream ost;
503 dumpControlFlow( ost, m_headNode, 0 );
504 return ost.str();
505 }
506
507 void PrecedenceRulesGraph::dumpControlFlow( std::ostringstream& ost, ControlFlowNode* node,
508 const int& indent ) const {
509 ost << std::string( indent * 2, ' ' );
510 DecisionNode* dn = dynamic_cast<DecisionNode*>( node );
511 AlgorithmNode* an = dynamic_cast<AlgorithmNode*>( node );
512 if ( dn != 0 ) {
513 if ( node != m_headNode ) {
514 ost << node->getNodeName() << " [Seq] ";
515 ost << ( ( dn->m_modeConcurrent ) ? " [Concurrent] " : " [Sequential] " );
516 ost << ( ( dn->m_modePromptDecision ) ? " [Prompt] " : "" );
517 ost << ( ( dn->m_modeOR ) ? " [OR] " : "" );
518 ost << ( ( dn->m_allPass ) ? " [PASS] " : "" );
519 ost << "\n";
520 }
521 for ( const auto& i : dn->getDaughters() ) dumpControlFlow( ost, i, indent + 1 );
522 } else if ( an != 0 ) {
523 ost << node->getNodeName() << " [Alg] ";
524 if ( an != 0 ) {
525 auto ar = an->getAlgorithm();
526 ost << " [n= " << ar->cardinality() << "]";
527 ost << ( ( !ar->isClonable() ) ? " [unclonable] " : "" );
528 }
529 ost << "\n";
530 }
531 }
532
533 //---------------------------------------------------------------------------
534 std::string PrecedenceRulesGraph::dumpDataFlow() const {
535
536 const char idt[] = " ";
537 std::ostringstream ost;
538
539 ost << "\n" << idt << "====================================\n";
540 ost << idt << "Data origins and destinations:\n";
541 ost << idt << "====================================\n";
542
543 for ( auto& pair : m_dataPathToDataNodeMap ) {
544
545 for ( auto algoNode : pair.second->getProducers() ) ost << idt << " " << algoNode->getNodeName() << "\n";
546
547 ost << idt << " V\n";
548 ost << idt << " o " << pair.first << "\n";
549 ost << idt << " V\n";
550
551 for ( auto algoNode : pair.second->getConsumers() ) ost << idt << " " << algoNode->getNodeName() << "\n";
552
553 ost << idt << "====================================\n";
554 }
555
556 return ost.str();
557 }
558
559 //---------------------------------------------------------------------------
560
561 void PrecedenceRulesGraph::dumpPrecRules( const boost::filesystem::path& fileName, const EventSlot& slot ) {
562 boost::filesystem::ofstream myfile;
563 myfile.open( fileName, std::ios::app );
564
565 // Declare properties to dump
566 boost::dynamic_properties dp;
567
568 dp.property( "Entity",
569 boost::make_transform_value_property_map(
570 []( const VariantVertexProps& v ) {
571 return std::visit( []( const auto& w ) { return boost::lexical_cast<std::string>( w ); }, v );
572 },
573 boost::get( boost::vertex_bundle, m_PRGraph ) ) );
574
575 auto add_prop = [&]( auto name, auto&& vis ) {
576 dp.property( name, boost::make_transform_value_property_map(
577 [vis = std::forward<decltype( vis )>( vis )]( const VariantVertexProps& v ) {
578 return std::visit( vis, v );
579 },
580 boost::get( boost::vertex_bundle, m_PRGraph ) ) );
581 };
582
583 add_prop( "Name", precedence::VertexName() );
584 add_prop( "Mode", precedence::GroupMode() );
585 add_prop( "Logic", precedence::GroupLogic() );
586 add_prop( "Decision Negation", precedence::DecisionNegation() );
587 add_prop( "Negative Decision Inversion", precedence::AllPass() );
588 add_prop( "Exit Policy", precedence::GroupExit() );
589 add_prop( "Operations", precedence::Operations() );
590 add_prop( "CF Decision", precedence::CFDecision( slot ) );
591 add_prop( "State", precedence::EntityState( slot, serviceLocator(), m_conditionsRealmEnabled ) );
592 add_prop( "Start Time (Epoch ns)", precedence::StartTime( slot, serviceLocator() ) );
593 add_prop( "End Time (Epoch ns)", precedence::EndTime( slot, serviceLocator() ) );
594 add_prop( "Runtime (ns)", precedence::Duration( slot, serviceLocator() ) );
595
596 boost::write_graphml( myfile, m_PRGraph, dp );
597
598 myfile.close();
599 }
600
601 //---------------------------------------------------------------------------
602 void PrecedenceRulesGraph::dumpPrecTrace( const boost::filesystem::path& fileName ) {
603 boost::filesystem::ofstream myfile;
604 myfile.open( fileName, std::ios::app );
605
606 // Fill runtimes (as this could not be done on the fly during trace assembling)
607 SmartIF<ITimelineSvc> timelineSvc = m_svcLocator->service<ITimelineSvc>( "TimelineSvc", false );
608 if ( !timelineSvc.isValid() ) {
609 warning() << "Failed to get the TimelineSvc, timing will not be added to "
610 << "the task precedence trace dump" << endmsg;
611 } else {
612
613 for ( auto vp = vertices( m_precTrace ); vp.first != vp.second; ++vp.first ) {
614 TimelineEvent te{};
615 te.algorithm = m_precTrace[*vp.first].m_name;
616 timelineSvc->getTimelineEvent( te );
617 int runtime = std::chrono::duration_cast<std::chrono::microseconds>( te.end - te.start ).count();
618 m_precTrace[*vp.first].m_runtime = runtime;
619 }
620 }
621
622 // Declare properties to dump
623 boost::dynamic_properties dp;
624 using boost::get;
625 using precedence::AlgoTraceProps;
626 dp.property( "Name", get( &AlgoTraceProps::m_name, m_precTrace ) );
627 dp.property( "Rank", get( &AlgoTraceProps::m_rank, m_precTrace ) );
628 dp.property( "Runtime", get( &AlgoTraceProps::m_runtime, m_precTrace ) );
629
630 boost::write_graphml( myfile, m_precTrace, dp );
631
632 myfile.close();
633 }
634
635 void PrecedenceRulesGraph::addEdgeToPrecTrace( const AlgorithmNode* u, const AlgorithmNode* v ) {
636
637 std::string u_name = u == nullptr ? "ENTRY" : u->getNodeName();
638 std::string v_name = v->getNodeName();
639
640 precedence::AlgoTraceVertex source;
641
642 if ( !u ) {
643 auto itT = m_prec_trace_map.find( "ENTRY" );
644 if ( itT != m_prec_trace_map.end() ) {
645 source = itT->second;
646 } else {
647 source = boost::add_vertex( precedence::AlgoTraceProps( "ENTRY", -1, -1, -1.0 ), m_precTrace );
648 m_prec_trace_map["ENTRY"] = source;
649 }
650 } else {
651 auto itS = m_prec_trace_map.find( u_name );
652 if ( itS != m_prec_trace_map.end() ) {
653 source = itS->second;
654 } else {
655
656 source =
657 boost::add_vertex( precedence::AlgoTraceProps( u_name, u->getAlgoIndex(), u->getRank(), -1 ), m_precTrace );
658 m_prec_trace_map[u_name] = source;
659 }
660 }
661
662 precedence::AlgoTraceVertex target;
663
664 auto itP = m_prec_trace_map.find( v_name );
665 if ( itP != m_prec_trace_map.end() ) {
666 target = itP->second;
667 } else {
668
669 target =
670 boost::add_vertex( precedence::AlgoTraceProps( v_name, v->getAlgoIndex(), v->getRank(), -1 ), m_precTrace );
671 m_prec_trace_map[v_name] = target;
672 }
673
674 boost::add_edge( source, target, m_precTrace );
675
676 ON_DEBUG debug() << u_name << "-->" << v_name << " precedence trait added" << endmsg;
677 }
678
679 } // namespace concurrency
concurrency::PrecedenceRulesGraph::m_algoNameToAlgoInputsMap
std::unordered_map< std::string, DataObjIDColl > m_algoNameToAlgoInputsMap
Indexes: maps of algorithm's name to algorithm's inputs/outputs.
Definition: PrecedenceRulesGraph.h:705
concurrency::AlgorithmNode::m_outputs
std::vector< DataNode * > m_outputs
Algorithm outputs (DataNodes)
Definition: PrecedenceRulesGraph.h:549
precedence::CFDecision
Definition: PrecedenceRulesGraph.h:172
SmartIF< ICondSvc >
EventSlot
Class representing an event slot.
Definition: EventSlot.h:14
precedence::GroupMode
Definition: PrecedenceRulesGraph.h:128
concurrency::DecisionNode::m_parents
std::vector< DecisionNode * > m_parents
Direct parent nodes.
Definition: PrecedenceRulesGraph.h:469
concurrency::DecisionNode
Definition: PrecedenceRulesGraph.h:430
precedence::Duration
Definition: PrecedenceRulesGraph.h:328
concurrency::ControlFlowNode::getNodeName
const std::string & getNodeName() const
Get node name.
Definition: PrecedenceRulesGraph.h:420
concurrency::AlgorithmNode::m_algoIndex
unsigned int m_algoIndex
The index of the algorithm.
Definition: PrecedenceRulesGraph.h:536
concurrency::PrecedenceRulesGraph::m_precTrace
precedence::PrecTrace m_precTrace
facilities for algorithm precedence tracing
Definition: PrecedenceRulesGraph.h:718
GaudiPython.HistoUtils.path
path
Definition: HistoUtils.py:932
gaudiComponentHelp.name
name
Definition: gaudiComponentHelp.py:41
concurrency::DecisionNode::addDaughterNode
void addDaughterNode(ControlFlowNode *node)
Add a daughter node.
Definition: PrecedenceRulesGraph.cpp:36
precedence::AlgoTraceVertex
boost::graph_traits< PrecTrace >::vertex_descriptor AlgoTraceVertex
Definition: PrecedenceRulesGraph.h:51
concurrency::PrecedenceRulesGraph::serviceLocator
SmartIF< ISvcLocator > & serviceLocator() const override
Retrieve pointer to service locator.
Definition: PrecedenceRulesGraph.h:665
DataObjID
Definition: DataObjID.h:37
concurrency::AlgorithmNode::getParentDecisionHubs
const std::vector< DecisionNode * > & getParentDecisionHubs() const
Get all parent decision hubs.
Definition: PrecedenceRulesGraph.h:494
CommonMessagingBase::warning
MsgStream & warning() const
shortcut for the method msgStream(MSG::WARNING)
Definition: CommonMessaging.h:101
concurrency::DataNode
Definition: PrecedenceRulesGraph.h:555
precedence::PRVertexDesc
boost::graph_traits< PRGraph >::vertex_descriptor PRVertexDesc
Definition: PrecedenceRulesGraph.h:383
gaudirun.output
output
Definition: gaudirun.py:484
concurrency::PrecedenceRulesGraph::addAlgorithmNode
StatusCode addAlgorithmNode(Gaudi::Algorithm *daughterAlgo, const std::string &parentName, bool inverted, bool allPass)
Add algorithm node.
Definition: PrecedenceRulesGraph.cpp:309
concurrency
Definition: PrecedenceRulesGraph.cpp:27
concurrency::IGraphVisitor::visit
virtual bool visit(DecisionNode &)
Definition: IGraphVisitor.h:16
concurrency::DecisionNode::m_children
std::vector< ControlFlowNode * > m_children
All direct daughter nodes in the tree.
Definition: PrecedenceRulesGraph.h:467
precedence::AlgoProps
Definition: PrecedenceRulesGraph.h:54
concurrency::IGraphVisitor::visitEnter
virtual bool visitEnter(DecisionNode &) const
Definition: IGraphVisitor.h:15
concurrency::AlgorithmNode::getAlgorithm
Gaudi::Algorithm * getAlgorithm() const
get Algorithm representatives
Definition: PrecedenceRulesGraph.h:511
concurrency::PrecedenceRulesGraph::dumpPrecRules
void dumpPrecRules(const boost::filesystem::path &, const EventSlot &slot)
dump to file the precedence rules
Definition: PrecedenceRulesGraph.cpp:561
std::endl
T endl(T... args)
SmartIF::isValid
bool isValid() const
Allow for check if smart pointer is valid.
Definition: SmartIF.h:62
Promoters.h
concurrency::PrecedenceRulesGraph::m_prec_trace_map
std::map< std::string, precedence::AlgoTraceVertex > m_prec_trace_map
Definition: PrecedenceRulesGraph.h:719
StatusCode::SUCCESS
constexpr static const auto SUCCESS
Definition: StatusCode.h:85
concurrency::AlgorithmNode::m_parents
std::vector< DecisionNode * > m_parents
Control flow parents of an AlgorithmNode (DecisionNodes)
Definition: PrecedenceRulesGraph.h:530
concurrency::ControlFlowNode
Definition: PrecedenceRulesGraph.h:405
ITimelineSvc::getTimelineEvent
virtual bool getTimelineEvent(TimelineEvent &) const =0
TimelineEvent::algorithm
std::string algorithm
Definition: ITimelineSvc.h:21
precedence::AlgoTraceProps
Definition: PrecedenceRulesGraph.h:39
EventSlot::controlFlowState
std::vector< int > controlFlowState
State of the control flow.
Definition: EventSlot.h:77
concurrency::PrecedenceRulesGraph::m_algoCounter
unsigned int m_algoCounter
Total number of algorithm nodes in the graph.
Definition: PrecedenceRulesGraph.h:711
std::map::end
T end(T... args)
EventSlot::allSubSlots
std::vector< EventSlot > allSubSlots
Actual sub-slot instances.
Definition: EventSlot.h:90
concurrency::PrecedenceRulesGraph::addDataNode
StatusCode addDataNode(const DataObjID &dataPath)
Add DataNode that represents DataObject.
Definition: PrecedenceRulesGraph.cpp:362
CommonMessagingBase::info
MsgStream & info() const
shortcut for the method msgStream(MSG::INFO)
Definition: CommonMessaging.h:104
ON_DEBUG
#define ON_DEBUG
Definition: PrecedenceRulesGraph.cpp:9
concurrency::DecisionNode::m_allPass
bool m_allPass
Whether always passing regardless of daughter results.
Definition: PrecedenceRulesGraph.h:463
TimelineEvent
Definition: ITimelineSvc.h:13
std::remove
T remove(T... args)
concurrency::PrecedenceRulesGraph::m_dataPathToDataNodeMap
std::unordered_map< DataObjID, std::unique_ptr< DataNode >, DataObjID_Hasher > m_dataPathToDataNodeMap
Index: map of data path to DataNode.
Definition: PrecedenceRulesGraph.h:703
std::stringstream
STL class.
concurrency::ModeOr
Gaudi::tagged_bool< class ModeOr_tag > ModeOr
Definition: PrecedenceRulesGraph.h:31
concurrency::DataReadyPromoter::visitEnter
bool visitEnter(AlgorithmNode &) const override
Definition: Promoters.cpp:14
std::string
STL class.
concurrency::AlgorithmNode::getAlgoIndex
const unsigned int & getAlgoIndex() const
Get algorithm index.
Definition: PrecedenceRulesGraph.h:513
concurrency::DecisionNode::m_modeOR
bool m_modeOR
Whether acting as "and" (false) or "or" node (true)
Definition: PrecedenceRulesGraph.h:461
std::vector::at
T at(T... args)
ISvcLocator::service
StatusCode service(const Gaudi::Utils::TypeNameString &name, T *&svc, bool createIf=true)
Templated method to access a service by name.
Definition: ISvcLocator.h:76
concurrency::AlgorithmNode::addInputDataNode
void addInputDataNode(DataNode *node)
Associate an AlgorithmNode, which is a data consumer of this one.
Definition: PrecedenceRulesGraph.cpp:193
concurrency::DecisionNode::accept
bool accept(IGraphVisitor &visitor) override
Visitor entry point.
Definition: PrecedenceRulesGraph.cpp:54
concurrency::PrecedenceRulesGraph::initialize
StatusCode initialize()
Initialize graph.
Definition: PrecedenceRulesGraph.cpp:199
concurrency::PrecedenceRulesGraph::m_algoNameToAlgoNodeMap
std::unordered_map< std::string, std::unique_ptr< AlgorithmNode > > m_algoNameToAlgoNodeMap
Index: map of algorithm's name to AlgorithmNode.
Definition: PrecedenceRulesGraph.h:699
concurrency::PrecedenceRulesGraph::dumpPrecTrace
void dumpPrecTrace(const boost::filesystem::path &)
dump to file the precedence trace
Definition: PrecedenceRulesGraph.cpp:602
concurrency::PrecedenceRulesGraph::m_conditionsRealmEnabled
bool m_conditionsRealmEnabled
Enable conditions realm of precedence rules.
Definition: PrecedenceRulesGraph.h:725
CommonMessagingBase::error
MsgStream & error() const
shortcut for the method msgStream(MSG::ERROR)
Definition: CommonMessaging.h:98
precedence::GroupExit
Definition: PrecedenceRulesGraph.h:146
concurrency::PrecedenceRulesGraph::m_PRGraph
precedence::PRGraph m_PRGraph
BGL-based graph of precedence rules.
Definition: PrecedenceRulesGraph.h:722
concurrency::Inverted
Gaudi::tagged_bool< class Inverted_tag > Inverted
Definition: PrecedenceRulesGraph.h:33
concurrency::PrecedenceRulesGraph::m_headNode
DecisionNode * m_headNode
the head node of the control flow graph
Definition: PrecedenceRulesGraph.h:697
concurrency::ControlFlowNode::m_nodeIndex
unsigned int m_nodeIndex
Definition: PrecedenceRulesGraph.h:426
StatusCode
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:50
concurrency::PrecedenceRulesGraph::dumpControlFlow
std::string dumpControlFlow() const
Print out control flow of Algorithms and Sequences.
Definition: PrecedenceRulesGraph.cpp:501
std::ostringstream
STL class.
CommonMessagingBase::verbose
MsgStream & verbose() const
shortcut for the method msgStream(MSG::VERBOSE)
Definition: CommonMessaging.h:110
precedence::EndTime
Definition: PrecedenceRulesGraph.h:289
std::ostringstream::str
T str(T... args)
concurrency::AlgorithmNode::getRank
const float & getRank() const
Get Algorithm rank.
Definition: PrecedenceRulesGraph.h:508
concurrency::IGraphVisitor
Definition: IGraphVisitor.h:11
CommonMessagingBase::debug
MsgStream & debug() const
shortcut for the method msgStream(MSG::DEBUG)
Definition: CommonMessaging.h:107
concurrency::PrecedenceRulesGraph::registerIODataObjects
void registerIODataObjects(const Gaudi::Algorithm *algo)
Register algorithm in the Data Dependency index.
Definition: PrecedenceRulesGraph.cpp:242
concurrency::PrecedenceRulesGraph::m_algoNameToAlgoOutputsMap
std::unordered_map< std::string, DataObjIDColl > m_algoNameToAlgoOutputsMap
Definition: PrecedenceRulesGraph.h:706
ITimelineSvc
Definition: ITimelineSvc.h:27
StatusCode::isSuccess
bool isSuccess() const
Definition: StatusCode.h:267
precedence::VertexName
Definition: PrecedenceRulesGraph.h:120
concurrency::DecisionNode::getDaughters
const std::vector< ControlFlowNode * > & getDaughters() const
Get children nodes.
Definition: PrecedenceRulesGraph.h:450
std::move
T move(T... args)
concurrency::Concurrent
Gaudi::tagged_bool< class Concurrent_tag > Concurrent
Definition: PrecedenceRulesGraph.h:29
concurrency::DecisionNode::m_modePromptDecision
bool m_modePromptDecision
Whether to evaluate the hub decision ASA its child decisions allow to do that.
Definition: PrecedenceRulesGraph.h:459
concurrency::PrecedenceRulesGraph::node
PRVertexDesc node(const std::string &) const
Definition: PrecedenceRulesGraph.cpp:470
precedence::EntityState
Definition: PrecedenceRulesGraph.h:188
concurrency::PrecedenceRulesGraph::addEdgeToPrecTrace
void addEdgeToPrecTrace(const AlgorithmNode *u, const AlgorithmNode *v)
set cause-effect connection between two algorithms in the precedence trace
Definition: PrecedenceRulesGraph.cpp:635
concurrency::ControlFlowNode::m_nodeName
std::string m_nodeName
Definition: PrecedenceRulesGraph.h:427
precedence::StartTime
Definition: PrecedenceRulesGraph.h:249
std::unique_ptr::get
T get(T... args)
DataHandleFinder
Implements the IDataHandleVisitor interface Class used to explore heirarchy of nested IDataHandleHold...
Definition: DataHandleFinder.h:21
concurrency::AlgorithmNode::addOutputDataNode
void addOutputDataNode(DataNode *node)
Associate an AlgorithmNode, which is a data supplier for this one.
Definition: PrecedenceRulesGraph.cpp:187
DataHandleHolderBase::outputDataObjs
const DataObjIDColl & outputDataObjs() const override
Definition: DataHandleHolderBase.h:56
std::find
T find(T... args)
concurrency::PrecedenceRulesGraph::m_decisionNameToDecisionHubMap
std::unordered_map< std::string, std::unique_ptr< DecisionNode > > m_decisionNameToDecisionHubMap
Index: map of decision's name to DecisionHub.
Definition: PrecedenceRulesGraph.h:701
Gaudi::Functional::details::get
auto get(const Handle &handle, const Algo &, const EventContext &) -> decltype(details::deref(handle.get()))
Definition: FunctionalDetails.h:332
std::vector< EventSlot >
Gaudi::Algorithm::acceptDHVisitor
void acceptDHVisitor(IDataHandleVisitor *) const override
Definition: Algorithm.cpp:194
std::unique_ptr< concurrency::DataNode >
concurrency::PrecedenceRulesGraph::addDecisionHubNode
StatusCode addDecisionHubNode(Gaudi::Algorithm *daughterAlgo, const std::string &parentName, concurrency::Concurrent, concurrency::PromptDecision, concurrency::ModeOr, concurrency::AllPass, concurrency::Inverted)
Add a node, which aggregates decisions of direct daughter nodes.
Definition: PrecedenceRulesGraph.cpp:392
precedence::DecisionNegation
Definition: PrecedenceRulesGraph.h:156
concurrency::PrecedenceRulesGraph::accept
void accept(IGraphVisitor &visitor) const
An entry point to visit all graph nodes.
Definition: PrecedenceRulesGraph.cpp:479
concurrency::PromptDecision
Gaudi::tagged_bool< class PromptDecision_tag > PromptDecision
Definition: PrecedenceRulesGraph.h:30
concurrency::AlgorithmNode::m_inputs
std::vector< DataNode * > m_inputs
Algorithm inputs (DataNodes)
Definition: PrecedenceRulesGraph.h:551
concurrency::DecisionNode::addParentNode
void addParentNode(DecisionNode *node)
Add a parent node.
Definition: PrecedenceRulesGraph.cpp:30
concurrency::DecisionNode::m_modeConcurrent
bool m_modeConcurrent
Whether all daughters will be evaluated concurrently or sequentially.
Definition: PrecedenceRulesGraph.h:456
concurrency::AlgorithmNode::getInputDataNodes
const std::vector< DataNode * > & getInputDataNodes() const
Get all consumer nodes.
Definition: PrecedenceRulesGraph.h:503
precedence::CondDataProps
Definition: PrecedenceRulesGraph.h:114
precedence::Operations
Definition: PrecedenceRulesGraph.h:366
concurrency::PrecedenceRulesGraph::name
const std::string & name() const override
Retrieve name of the service.
Definition: PrecedenceRulesGraph.h:663
DataHandleFinder.h
concurrency::ConditionNode
Definition: PrecedenceRulesGraph.h:593
concurrency::PrecedenceRulesGraph::m_nodeCounter
unsigned int m_nodeCounter
Total number of nodes in the graph.
Definition: PrecedenceRulesGraph.h:709
Gaudi::Algorithm
Base class from which all concrete algorithm classes should be derived.
Definition: Algorithm.h:79
concurrency::DecisionNode::printState
void printState(std::stringstream &output, EventSlot &slot, const unsigned int &recursionLevel) const override
Print a string representing the control flow state.
Definition: PrecedenceRulesGraph.cpp:42
concurrency::PrecedenceRulesGraph::getDataNode
DataNode * getDataNode(const DataObjID &dataPath) const
Get DataNode by DataObject path using graph index.
Definition: PrecedenceRulesGraph.h:634
concurrency::AllPass
Gaudi::tagged_bool< class AllPass_tag > AllPass
Definition: PrecedenceRulesGraph.h:32
StatusCode::FAILURE
constexpr static const auto FAILURE
Definition: StatusCode.h:86
EventSlot::parentSlot
EventSlot * parentSlot
Pointer to parent slot (null for top level)
Definition: EventSlot.h:86
concurrency::AlgorithmNode
Definition: PrecedenceRulesGraph.h:475
concurrency::AlgorithmNode::addParentNode
void addParentNode(DecisionNode *node)
Add a parent node.
Definition: PrecedenceRulesGraph.cpp:181
concurrency::DataReadyPromoter
Definition: Promoters.h:11
concurrency::AlgorithmNode::accept
bool accept(IGraphVisitor &visitor) override
Visitor entry point.
Definition: PrecedenceRulesGraph.cpp:170
precedence::GroupLogic
Definition: PrecedenceRulesGraph.h:138
concurrency::PrecedenceRulesGraph::dumpDataFlow
std::string dumpDataFlow() const
Print out all data origins and destinations, as reflected in the EF graph.
Definition: PrecedenceRulesGraph.cpp:534
ON_VERBOSE
#define ON_VERBOSE
Definition: PrecedenceRulesGraph.cpp:10
concurrency::PrecedenceRulesGraph::buildDataDependenciesRealm
StatusCode buildDataDependenciesRealm()
Build data dependency realm WITH data object nodes participating.
Definition: PrecedenceRulesGraph.cpp:261
precedence::AllPass
Definition: PrecedenceRulesGraph.h:164
precedence::DecisionHubProps
Definition: PrecedenceRulesGraph.h:80
DataHandleHolderBase::inputDataObjs
const DataObjIDColl & inputDataObjs() const override
Definition: DataHandleHolderBase.h:55
EventSlot::subSlotsByNode
std::unordered_map< std::string, std::vector< unsigned int > > subSlotsByNode
Listing of sub-slots by the node (name) they are attached to.
Definition: EventSlot.h:88
concurrency::AlgorithmNode::printState
void printState(std::stringstream &output, EventSlot &slot, const unsigned int &recursionLevel) const override
Print a string representing the control flow state.
Definition: PrecedenceRulesGraph.cpp:66
std::forward
T forward(T... args)
precedence::VariantVertexProps
std::variant< AlgoProps, DecisionHubProps, DataProps, CondDataProps > VariantVertexProps
Definition: PrecedenceRulesGraph.h:381
PrecedenceRulesGraph.h
endmsg
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:192
concurrency::PrecedenceRulesGraph::m_enableAnalysis
bool m_enableAnalysis
Definition: PrecedenceRulesGraph.h:720
concurrency::PrecedenceRulesGraph::addHeadNode
void addHeadNode(const std::string &headName, concurrency::Concurrent, concurrency::PromptDecision, concurrency::ModeOr, concurrency::AllPass, concurrency::Inverted)
Add a node, which has no parents.
Definition: PrecedenceRulesGraph.cpp:445
Gaudi::Algorithm::name
const std::string & name() const override
The identifying name of the algorithm object.
Definition: Algorithm.cpp:645
EventSlot::algsStates
AlgsExecutionStates algsStates
Vector of algorithms states.
Definition: EventSlot.h:75
precedence::DataProps
Definition: PrecedenceRulesGraph.h:108
concurrency::PrecedenceRulesGraph::m_svcLocator
SmartIF< ISvcLocator > m_svcLocator
Service locator (needed to access the MessageSvc)
Definition: PrecedenceRulesGraph.h:714
concurrency::PrecedenceRulesGraph::rankAlgorithms
void rankAlgorithms(IGraphVisitor &ranker) const
Rank Algorithm nodes by the number of data outputs.
Definition: PrecedenceRulesGraph.cpp:491
concurrency::DataNode::addConsumerNode
void addConsumerNode(AlgorithmNode *node)
Add relationship to consumer AlgorithmNode.
Definition: PrecedenceRulesGraph.h:575