38#include <unordered_set>
41#include <boost/algorithm/string.hpp>
42#include <boost/thread.hpp>
43#include <boost/tokenizer.hpp>
48#define ON_DEBUG if ( msgLevel( MSG::DEBUG ) )
49#define ON_VERBOSE if ( msgLevel( MSG::VERBOSE ) )
53 constexpr std::chrono::seconds s_dumpStateTimeout{ 30 };
55 struct DataObjIDSorter {
61 std::vector<const DataObjID*> sortedDataObjIDColl(
const DataObjIDColl& coll ) {
62 std::vector<const DataObjID*> v;
63 v.reserve( coll.size() );
64 for (
const DataObjID&
id : coll ) v.push_back( &
id );
65 std::sort( v.begin(), v.end(), DataObjIDSorter() );
69 bool subSlotAlgsInStates(
const EventSlot& slot, std::initializer_list<AlgsExecutionStates::State> testStates ) {
71 [testStates](
const EventSlot& ss ) { return ss.algsStates.containsAny( testStates ); } );
92 fatal() <<
"Error retrieving ThreadPoolSvc" <<
endmsg;
102 fatal() <<
"Cannot find valid TBB task_arena" <<
endmsg;
107 info() <<
"Activating scheduler in a separate thread" <<
endmsg;
108 std::binary_semaphore fiber_manager_initalized{ 0 };
109 m_thread = std::thread( [
this, &fiber_manager_initalized]() {
112 std::make_unique<FiberManager>( this->
m_numOffloadThreads.value(), this->m_fiberStackSize.value() );
113 fiber_manager_initalized.release();
117 fiber_manager_initalized.acquire();
133 warning() <<
"No CondSvc found, or not enabled. "
134 <<
"Will not manage CondAlgorithms" <<
endmsg;
142 fatal() <<
"Error retrieving AlgoResourcePool" <<
endmsg;
148 fatal() <<
"Error retrieving AlgExecStateSvc" <<
endmsg;
155 fatal() <<
"Error retrieving EventDataSvc interface IHiveWhiteBoard." <<
endmsg;
167 const unsigned int algsNumber = algos.size();
168 if ( algsNumber != 0 ) {
169 info() <<
"Found " << algsNumber <<
" algorithms" <<
endmsg;
182 auto hasAsynchronousAlgorithms =
false;
185 std::map<std::string, DataObjIDColl> algosOutputDependenciesMap;
189 fatal() <<
"Could not convert IAlgorithm into Gaudi::Algorithm: this will result in a crash." <<
endmsg;
195 globalOutp.insert(
id );
196 algoOutputs.insert(
id );
198 algosOutputDependenciesMap[algoPtr->
name()] = algoOutputs;
200 hasAsynchronousAlgorithms = hasAsynchronousAlgorithms || algoPtr->
isAsynchronous();
205 <<
"; no fiber pool threads will be available to execute them." <<
endmsg;
209 std::ostringstream ostdd;
210 ostdd <<
"Data Dependencies for Algorithms:";
212 std::map<std::string, DataObjIDColl> algosInputDependenciesMap;
215 if (
nullptr == algoPtr ) {
216 fatal() <<
"Could not convert IAlgorithm into Gaudi::Algorithm for " << ialgoPtr->name()
217 <<
": this will result in a crash." <<
endmsg;
225 ostdd <<
"\n " << algoPtr->
name();
227 auto write_owners = [&avis, &ostdd](
const DataObjID& id ) {
236 ostdd <<
"\n o INPUT " << id;
238 algoDependencies.insert(
id );
239 globalInp.insert(
id );
242 ostdd <<
"\n o OUTPUT " << *id;
244 if ( id->key().find(
":" ) != std::string::npos ) {
245 error() <<
" in Alg " << algoPtr->
name() <<
" alternatives are NOT allowed for outputs! id: " << *
id
253 algosInputDependenciesMap[algoPtr->
name()] = algoDependencies;
269 std::set<std::string> requiredInputKeys;
270 for (
auto o : globalInp ) {
273 requiredInputKeys.insert( o.key() );
274 if ( globalOutp.find( o ) == globalOutp.end() ) unmetDepInp.insert( o );
277 for (
auto o : globalOutp ) {
278 if ( globalInp.find( o ) == globalInp.end() && requiredInputKeys.find( o.key() ) == requiredInputKeys.end() ) {
282 auto it = algosOutputDependenciesMap.find( algoName );
283 if ( it != algosOutputDependenciesMap.end() ) {
284 if ( it->second.find( o ) != it->second.end() ) {
290 if ( !ignored ) { unusedOutp.insert( o ); }
297 if ( unmetDepInp.size() > 0 ) {
299 auto printUnmet = [&](
auto msg ) {
300 for (
const DataObjID* o : sortedDataObjIDColl( unmetDepInp ) ) {
301 msg <<
" o " << *o <<
" required by Algorithm: " <<
endmsg;
303 for (
const auto& p : algosInputDependenciesMap )
304 if ( p.second.find( *o ) != p.second.end() )
msg <<
" * " << p.first <<
endmsg;
314 dataLoaderAlg = algo;
318 if ( dataLoaderAlg ==
nullptr ) {
320 <<
"\" found, and unmet INPUT dependencies "
322 printUnmet(
fatal() );
326 info() <<
"Will attribute the following unmet INPUT dependencies to \"" << dataLoaderAlg->
type() <<
"/"
327 << dataLoaderAlg->name() <<
"\" Algorithm" <<
endmsg;
328 printUnmet(
info() );
333 fatal() <<
"Unable to dcast DataLoader \"" <<
m_useDataLoader.value() <<
"\" IAlg to Gaudi::Algorithm"
338 for (
auto&
id : unmetDepInp ) {
339 ON_DEBUG debug() <<
"adding OUTPUT dep \"" <<
id <<
"\" to " << dataLoaderAlg->
type() <<
"/"
340 << dataLoaderAlg->name() <<
endmsg;
345 fatal() <<
"Auto DataLoading not requested, "
346 <<
"and the following unmet INPUT dependencies were found:" <<
endmsg;
347 printUnmet(
fatal() );
352 info() <<
"No unmet INPUT data dependencies were found" <<
endmsg;
357 if ( unusedOutp.size() > 0 ) {
359 auto printUnusedOutp = [&](
auto msg ) {
360 for (
const DataObjID* o : sortedDataObjIDColl( unusedOutp ) ) {
361 msg <<
" o " << *o <<
" produced by Algorithm: " <<
endmsg;
363 for (
const auto& p : algosOutputDependenciesMap )
364 if ( p.second.find( *o ) != p.second.end() )
msg <<
" * " << p.first <<
endmsg;
368 fatal() <<
"The following unused OUTPUT items were found:" <<
endmsg;
369 printUnusedOutp(
fatal() );
372 info() <<
"No unused OUTPUT items were found" <<
endmsg;
379 fatal() <<
"Error retrieving PrecedenceSvc" <<
endmsg;
384 fatal() <<
"Unable to dcast PrecedenceSvc" <<
endmsg;
391 const std::string&
name = algo->name();
399 if ( !messageSvc.
isValid() )
error() <<
"Error retrieving MessageSvc interface IMessageSvc." <<
endmsg;
408 info() <<
"Concurrency level information:" <<
endmsg;
414 info() <<
"Task scheduling settings:" <<
endmsg;
415 info() <<
" o Avalanche generation mode: "
444 info() <<
"Joining Scheduler thread" <<
endmsg;
449 error() <<
"problems in scheduler thread" <<
endmsg;
472 error() <<
"problems initializing ThreadPoolSvc" <<
endmsg;
490 verbose() <<
"Action did not succeed (which is not bad per se)." <<
endmsg;
501 verbose() <<
"Iteration did not succeed (which is not bad per se)." <<
endmsg;
511 error() <<
"Problems terminating thread pool" <<
endmsg;
557 if ( !eventContext ) {
572 const unsigned int thisSlotNum = eventContext->
slot();
575 fatal() <<
"The slot " << thisSlotNum <<
" is supposed to be a finished event but it's not" <<
endmsg;
580 thisSlot.
reset( eventContext );
587 if (
m_precSvc->iterate( thisSlot, cs ).isFailure() ) {
588 error() <<
"Failed to call IPrecedenceSvc::iterate for slot " << thisSlotNum <<
endmsg;
592 if ( this->
iterate().isFailure() ) {
593 error() <<
"Failed to call AvalancheSchedulerSvc::updateStates for slot " << thisSlotNum <<
endmsg;
602 verbose() <<
"Pushing the action to update the scheduler for slot " << eventContext->
slot() <<
endmsg;
615 for (
auto context : eventContexts ) {
637 auto done = std::make_shared<std::promise<void>>();
638 auto future = done->get_future();
647 if ( future.wait_for( s_dumpStateTimeout ) != std::future_status::ready ) {
648 warning() <<
"The scheduler thread did not produce the state dump within " << s_dumpStateTimeout.count()
649 <<
"s (it may be blocked): the dump will appear when it proceeds" <<
endmsg;
681 ON_DEBUG debug() <<
"Try Pop successful slot " << eventContext->
slot() <<
"(event " << eventContext->
evt() <<
")"
704 for (
unsigned int retryIndex = 0; retryIndex < retries; ++retryIndex ) {
707 global_sc =
schedule( std::move( retryTS ) );
711 OccupancySnapshot nextSnap;
712 auto now = std::chrono::system_clock::now();
716 if ( !thisSlot.eventContext )
continue;
718 int iSlot = thisSlot.eventContext->slot();
730 if ( nextSnap.states.empty() ) {
736 std::vector<int>& slotStateTotals = nextSnap.states[iSlot];
737 slotStateTotals.resize( AState::MAXVALUE );
738 for ( uint8_t state = 0; state < AState::MAXVALUE; ++state ) {
739 slotStateTotals[state] = thisSlot.algsStates.sizeOfSubset(
AState( state ) );
743 for (
auto& subslot : thisSlot.allSubSlots ) {
744 for ( uint8_t state = 0; state < AState::MAXVALUE; ++state ) {
745 slotStateTotals[state] += subslot.algsStates.sizeOfSubset(
AState( state ) );
751 const auto& drAlgs = thisAlgsStates.
algsInState( AState::DATAREADY );
752 for ( uint algIndex : drAlgs ) {
755 bool asynchronous{
m_precSvc->isAsynchronous( algName ) };
758 schedule(
TaskSpec(
nullptr, algIndex, algName, rank, asynchronous, iSlot, thisSlot.eventContext.get() ) );
761 <<
"Could not apply transition from " << AState::DATAREADY <<
" for algorithm " << algName
762 <<
" on processing slot " << iSlot <<
endmsg;
766 for (
auto& subslot : thisSlot.allSubSlots ) {
767 const auto& drAlgsSubSlot = subslot.algsStates.algsInState( AState::DATAREADY );
768 for ( uint algIndex : drAlgsSubSlot ) {
771 bool asynchronous{
m_precSvc->isAsynchronous( algName ) };
773 schedule(
TaskSpec(
nullptr, algIndex, algName, rank, asynchronous, iSlot, subslot.eventContext.get() ) );
779 s <<
"START, " << thisAlgsStates.
sizeOfSubset( AState::CONTROLREADY ) <<
", "
781 <<
", " << std::chrono::high_resolution_clock::now().time_since_epoch().count() <<
"\n";
783 : std::to_string( std::thread::hardware_concurrency() );
784 std::ofstream myfile;
785 myfile.open(
"IntraEventFSMOccupancy_" + threads +
"T.csv", std::ios::app );
791 if (
m_precSvc->CFRulesResolved( thisSlot ) &&
792 !thisSlot.algsStates.containsAny(
793 { AState::CONTROLREADY, AState::DATAREADY, AState::SCHEDULED, AState::RESOURCELESS } ) &&
794 !subSlotAlgsInStates( thisSlot,
795 { AState::CONTROLREADY, AState::DATAREADY, AState::SCHEDULED, AState::RESOURCELESS } ) &&
796 !thisSlot.complete ) {
798 thisSlot.complete =
true;
802 ON_DEBUG debug() <<
"Event " << thisSlot.eventContext->evt() <<
" finished (slot "
803 << thisSlot.eventContext->slot() <<
")." <<
endmsg;
810 thisSlot.eventContext.reset(
nullptr );
820 if ( !nextSnap.states.empty() ) {
834 auto slotIndex = contextPtr->
slot();
840 auto subSlotIndex = contextPtr->
subSlot();
847 <<
", subslot:" << subSlotIndex <<
", event:" << contextPtr->
evt() <<
"]" <<
endmsg;
857 <<
", event:" << contextPtr->
evt() <<
"]" <<
endmsg;
875 if ( !slot.
algsStates.
containsAny( { AState::DATAREADY, AState::SCHEDULED, AState::RESOURCELESS } ) &&
876 !subSlotAlgsInStates( slot, { AState::DATAREADY, AState::SCHEDULED, AState::RESOURCELESS } ) ) {
892 const uint slotIdx = eventContext->
slot();
894 error() <<
"Event " << eventContext->
evt() <<
" on slot " << slotIdx <<
" failed" <<
endmsg;
915 std::ostringstream outputMS;
917 outputMS <<
"Dumping scheduler state\n"
918 <<
"=========================================================================================\n"
919 <<
"++++++++++++++++++++++++++++++++++++ SCHEDULER STATE ++++++++++++++++++++++++++++++++++++\n"
920 <<
"=========================================================================================\n\n";
924 outputMS <<
"------------------ Last schedule: Task/Event/Slot/Thread/State Mapping "
925 <<
"------------------\n\n";
929 if ( !timelineSvc.isValid() || !timelineSvc->isEnabled() ) {
930 outputMS <<
"WARNING Enable TimelineSvc in record mode (RecordTimeline = True) to trace the mapping\n";
937 const auto& schedAlgs = slot.algsStates.algsInState( AState::SCHEDULED );
938 for ( uint algIndex : schedAlgs ) {
946 const auto& schedAlgs = slot.algsStates.algsInState( AState::SCHEDULED );
947 for ( uint algIndex : schedAlgs ) {
951 outputMS <<
" task: " << std::setw( indt ) << algoName <<
" evt/slot: " << slot.eventContext->evt() <<
"/"
952 << slot.eventContext->slot();
955 if ( timelineSvc.isValid() ) {
958 te.
slot = slot.eventContext->slot();
959 te.
event = slot.eventContext->evt();
961 if ( timelineSvc->getLastMatching( te ) )
962 outputMS <<
" thread.id: 0x" << std::hex << te.
thread << std::dec;
964 outputMS <<
" thread.id: [unknown]";
969 outputMS <<
" state: [" <<
m_algExecStateSvc->algExecState( algoName, *( slot.eventContext ) ) <<
"]\n";
976 outputMS <<
"\n---------------------------- Task/CF/FSM Mapping "
977 << ( 0 > iSlot ?
"[all slots] --" :
"[target slot] " ) <<
"--------------------------\n\n";
980 bool wasAlgError = ( iSlot >= 0 ) ?
m_eventSlots[iSlot].algsStates.containsAny( { AState::ERROR } ) ||
981 subSlotAlgsInStates(
m_eventSlots[iSlot], { AState::ERROR } )
986 if ( slot.complete )
continue;
988 outputMS <<
"[ slot: "
989 << ( slot.eventContext->valid() ? std::to_string( slot.eventContext->slot() ) :
"[ctx invalid]" )
991 << ( slot.eventContext->valid() ? std::to_string( slot.eventContext->evt() ) :
"[ctx invalid]" );
993 if ( slot.eventContext->eventID().isValid() ) { outputMS <<
", eventID: " << slot.eventContext->eventID(); }
994 outputMS <<
" ]:\n\n";
996 if ( 0 > iSlot || iSlot == slotCount ) {
1000 outputMS <<
"ERROR alg(s):";
1002 const auto& errorAlgs = slot.algsStates.algsInState( AState::ERROR );
1003 for ( uint algIndex : errorAlgs ) {
1007 if ( errorCount == 0 ) outputMS <<
" in subslot(s)";
1011 outputMS <<
m_precSvc->printState( slot ) <<
"\n";
1016 outputMS <<
"\nNumber of sub-slots: " << slot.allSubSlots.size() <<
"\n\n";
1017 auto slotID = slot.eventContext->valid() ? std::to_string( slot.eventContext->slot() ) :
"[ctx invalid]";
1018 for (
auto& ss : slot.allSubSlots ) {
1019 outputMS <<
"[ slot: " << slotID <<
", sub-slot: "
1020 << ( ss.eventContext->valid() ? std::to_string( ss.eventContext->subSlot() ) :
"[ctx invalid]" )
1021 <<
", entry: " << ss.entryPoint <<
", event: "
1022 << ( ss.eventContext->valid() ? std::to_string( ss.eventContext->evt() ) :
"[ctx invalid]" )
1024 if ( wasAlgError ) {
1025 outputMS <<
"ERROR alg(s):";
1026 const auto& errorAlgs = ss.algsStates.algsInState( AState::ERROR );
1027 for ( uint algIndex : errorAlgs ) { outputMS <<
" " <<
index2algname( algIndex ); }
1031 outputMS <<
m_precSvc->printState( ss ) <<
"\n";
1040 if ( 0 <= iSlot && !wasAlgError ) {
1041 outputMS <<
"\n------------------------------ Algorithm Execution States -----------------------------\n\n";
1045 outputMS <<
"\n=========================================================================================\n"
1046 <<
"++++++++++++++++++++++++++++++++++++++ END OF DUMP ++++++++++++++++++++++++++++++++++++++\n"
1047 <<
"=========================================================================================\n\n";
1067 unsigned int algIndex{ ts.algIndex };
1068 std::string_view algName( ts.algName );
1069 unsigned int algRank{ ts.algRank };
1070 bool asynchronous{ ts.asynchronous };
1071 int slotIndex{ ts.slotIndex };
1074 if ( asynchronous ) {
1082 if ( !asynchronous ) {
1090 sc =
revise( algIndex, contextPtr, AState::SCHEDULED );
1092 ON_DEBUG debug() <<
"Scheduled " << algName <<
" [slot:" << slotIndex <<
", event:" << contextPtr->
evt()
1093 <<
", rank:" << algRank <<
", asynchronous:" << ( asynchronous ?
"yes" :
"no" )
1099 sc =
revise( ts.algIndex, ts.contextPtr, AState::SCHEDULED );
1105 sc =
revise( ts.algIndex, ts.contextPtr, AState::RESOURCELESS );
1128 ? ( algstate.
filterPassed() ? AState::EVTACCEPTED : AState::EVTREJECTED )
1132 auto sc =
revise( ts.algIndex, ts.contextPtr, state,
true );
1134 ON_DEBUG debug() <<
"Executed " << ts.algName <<
" [slot:" << ts.slotIndex <<
", event:" << ts.contextPtr->evt()
1135 <<
", rank:" << ts.algRank <<
", asynchronous:" << ( ts.asynchronous ?
"yes" :
"no" )
1148 std::unique_ptr<EventContext> viewContext ) {
1151 fatal() <<
"Attempted to nest EventViews at node " << nodeName <<
": this is not supported" <<
endmsg;
1159 auto action = [
this, slotIndex = sourceContext->
slot(), viewContextPtr = viewContext.release(),
1164 if ( viewContextPtr ) {
1166 auto viewContext = std::unique_ptr<EventContext>( viewContextPtr );
1167 topSlot.
addSubSlot( std::move( viewContext ), nodeName );
1189 auto action = [
this, samplePeriod, callback = std::move( callback )]() ->
StatusCode {
1190 if ( samplePeriod < 0 ) {
1193 this->
m_snapshotInterval = std::chrono::duration<int64_t, std::milli>( samplePeriod );
1203 const std::map<std::string, DataObjIDColl>& outDeps )
const {
1205 assert( inDeps.size() == outDeps.size() );
1208 info() <<
"Dumping data dependencies graph to file: " << g.fileName() <<
endmsg;
1211 std::set<std::size_t> definedObjects;
1218 std::size_t algoIndex = 0ul;
1219 for (
const auto& [algName, ideps] : inDeps ) {
1220 if ( not std::regex_search( algName, algNameRegex ) )
continue;
1221 std::string algIndex =
"Alg_" + std::to_string( algoIndex );
1222 g.addNode( algIndex, algName );
1225 for (
const auto& dep : ideps ) {
1226 if ( not std::regex_search( dep.fullKey(), objNameRegex ) )
continue;
1228 const auto [itr, inserted] = definedObjects.insert( dep.hash() );
1229 std::string objIndex =
"obj_" + std::to_string( dep.hash() );
1230 if ( inserted ) g.addNode( objIndex, dep.key() );
1232 g.addEdge( objIndex, algIndex );
1235 const auto& odeps = outDeps.at( algName );
1236 for (
const auto& dep : odeps ) {
1237 if ( not std::regex_search( dep.fullKey(), objNameRegex ) )
continue;
1239 const auto [itr, inserted] = definedObjects.insert( dep.hash() );
1240 std::string objIndex =
"obj_" + std::to_string( dep.hash() );
1241 if ( inserted ) g.addNode( objIndex, dep.key() );
1243 g.addEdge( algIndex, objIndex );
std::unordered_set< DataObjID, DataObjID_Hasher > DataObjIDColl
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
#define DECLARE_COMPONENT(type)
Provide serialization function (output only) for some common STL classes (vectors,...
wrapper on an Algorithm state.
const StatusCode & execStatus() const
bool filterPassed() const
The AlgsExecutionStates encodes the state machine for the execution of algorithms within a single eve...
const boost::container::flat_set< int > algsInState(State state) const
size_t sizeOfSubset(State state) const
bool containsAny(std::initializer_list< State > l) const
check if the collection contains at least one state of any listed types
StatusCode set(unsigned int iAlgo, State newState)
StatusCode pushNewEvent(EventContext *eventContext) override
Make an event available to the scheduler.
Gaudi::Property< std::vector< std::string > > m_checkOutputIgnoreList
SmartIF< IThreadPoolSvc > m_threadPoolSvc
Gaudi::Property< std::string > m_useDataLoader
void dumpState() override
Dump scheduler state for all slots.
void activate()
Activate scheduler.
Gaudi::Property< std::string > m_optimizationMode
StatusCode popFinishedEvent(EventContext *&eventContext) override
Blocks until an event is available.
Gaudi::Property< bool > m_dumpIntraEventDynamics
std::chrono::system_clock::time_point m_lastSnapshot
std::vector< std::string > m_algname_vect
Vector to bookkeep the information necessary to the index2name conversion.
Gaudi::Property< int > m_threadPoolSize
StatusCode finalize() override
Finalise.
tbb::concurrent_priority_queue< TaskSpec, AlgQueueSort > m_scheduledQueue
Queues for scheduled algorithms.
std::function< void(OccupancySnapshot)> m_snapshotCallback
std::queue< TaskSpec > m_retryQueue
Gaudi::Property< bool > m_verboseSubSlots
tbb::concurrent_bounded_queue< action > m_actionsQueue
Queue where closures are stored and picked for execution.
SmartIF< ICondSvc > m_condSvc
A shortcut to service for Conditions handling.
AlgsExecutionStates::State AState
bool isStalled(const EventSlot &) const
Check if scheduling in a particular slot is in a stall.
SmartIF< IAlgExecStateSvc > m_algExecStateSvc
Algorithm execution state manager.
StatusCode pushNewEvents(std::vector< EventContext * > &eventContexts) override
StatusCode revise(unsigned int iAlgo, EventContext *contextPtr, AState state, bool iterate=false)
tbb::concurrent_bounded_queue< EventContext * > m_finishedEvents
Queue of finished events.
StatusCode deactivate()
Deactivate scheduler.
size_t m_maxEventsInFlight
unsigned int m_algosInFlight
Number of algorithms presently in flight.
Gaudi::Property< std::string > m_dataDepsGraphObjectPattern
Gaudi::Property< bool > m_showDataFlow
StatusCode schedule(TaskSpec &&)
SmartIF< IPrecedenceSvc > m_precSvc
A shortcut to the Precedence Service.
Gaudi::Property< bool > m_checkDeps
std::chrono::duration< int64_t, std::milli > m_snapshotInterval
Gaudi::Property< std::string > m_dataDepsGraphFile
SmartIF< IAlgResourcePool > m_algResourcePool
Cache for the algorithm resource pool.
Gaudi::Property< bool > m_showControlFlow
Gaudi::Property< bool > m_simulateExecution
Gaudi::Property< std::string > m_whiteboardSvcName
StatusCode tryPopFinishedEvent(EventContext *&eventContext) override
Try to fetch an event from the scheduler.
std::unordered_map< std::string, unsigned int > m_algname_index_map
Map to bookkeep the information necessary to the name2index conversion.
std::atomic< bool > m_needsUpdate
virtual StatusCode scheduleEventView(const EventContext *sourceContext, const std::string &nodeName, std::unique_ptr< EventContext > viewContext) override
Method to inform the scheduler about event views.
Gaudi::Property< int > m_maxParallelismExtra
StatusCode signoff(const TaskSpec &)
The call to this method is triggered only from within the AlgTask.
std::function< StatusCode()> action
Gaudi::Property< std::string > m_dataDepsGraphAlgoPattern
Gaudi::Property< int > m_numOffloadThreads
Gaudi::Property< bool > m_checkOutput
std::atomic< ActivationState > m_isActive
Flag to track if the scheduler is active or not.
StatusCode initialize() override
Initialise.
Gaudi::Property< bool > m_enableCondSvc
virtual void recordOccupancy(int samplePeriod, std::function< void(OccupancySnapshot)> callback) override
Sample occupancy at fixed interval (ms) Negative value to deactivate, 0 to snapshot every change Each...
void eventFailed(EventContext *eventContext)
Method to execute if an event failed.
std::atomic_int m_freeSlots
Atomic to account for asyncronous updates by the scheduler wrt the rest.
tbb::task_arena * m_arena
StatusCode dumpDataDepsGraphFile(const std::map< std::string, DataObjIDColl > &inDeps, const std::map< std::string, DataObjIDColl > &outDeps) const
unsigned int freeSlots() override
Get free slots number.
void dumpSchedulerState(int iSlot)
Dump the state of the scheduler.
std::unique_ptr< FiberManager > m_fiberManager
SmartIF< IHiveWhiteBoard > m_whiteboard
A shortcut to the whiteboard.
tbb::concurrent_priority_queue< TaskSpec, AlgQueueSort > m_scheduledAsynchronousQueue
StatusCode iterate()
Loop on all slots to schedule DATAREADY algorithms and sign off ready events.
Gaudi::Property< bool > m_showDataDeps
std::thread m_thread
The thread in which the activate function runs.
const std::string & index2algname(unsigned int index)
Convert an integer to a name.
std::vector< EventSlot > m_eventSlots
Vector of events slots.
MsgStream & error() const
shortcut for the method msgStream(MSG::ERROR)
MsgStream & verbose() const
shortcut for the method msgStream(MSG::VERBOSE)
MsgStream & warning() const
shortcut for the method msgStream(MSG::WARNING)
MsgStream & fatal() const
shortcut for the method msgStream(MSG::FATAL)
MsgStream & debug() const
shortcut for the method msgStream(MSG::DEBUG)
MsgStream & msg() const
shortcut for the method msgStream(MSG::INFO)
MsgStream & info() const
shortcut for the method msgStream(MSG::INFO)
MSG::Level msgLevel() const
get the cached level (originally extracted from the embedded MsgStream)
std::vector< std::string > owners_names_of(const DataObjID &id, bool with_main=false) const
const DataObjIDColl & outputDataObjs() const override
void addDependency(const DataObjID &id, const Gaudi::DataHandle::Mode &mode) override
const DataObjIDColl & inputDataObjs() const override
std::string fullKey() const
combination of the key and the ClassName, mostly for debugging
This class represents an entry point to all the event specific data.
ContextID_t subSlot() const
Base class from which all concrete algorithm classes should be derived.
void acceptDHVisitor(IDataHandleVisitor *) const override
const std::string & name() const override
The identifying name of the algorithm object.
bool isAsynchronous() const
utilities to dump graphs in different formats
The IAlgorithm is the interface implemented by the Algorithm base class.
virtual const std::string & type() const =0
The type of the algorithm.
virtual SmartIF< IService > & service(const Gaudi::Utils::TypeNameString &typeName, const bool createIf=true)=0
Returns a smart pointer to a service.
A service to resolve the task execution precedence.
const concurrency::PrecedenceRulesGraph * getRules() const
Precedence rules accessor.
SmartIF< ISvcLocator > & serviceLocator() const override
Retrieve pointer to service locator.
StatusCode finalize() override
const std::string & name() const override
Retrieve name of the service.
StatusCode initialize() override
Small smart pointer class with automatic reference counting for IInterface.
bool isValid() const
Allow for check if smart pointer is valid.
This class is used for returning status codes from appropriate routines.
void ignore() const
Allow discarding a StatusCode without warning.
constexpr static const auto SUCCESS
constexpr static const auto FAILURE
A service which initializes a TBB thread pool.
unsigned int getAlgoIndex() const
Get algorithm index.
unsigned int getControlFlowNodeCounter() const
Get total number of control flow graph nodes.
AlgorithmNode * getAlgorithmNode(const std::string &algoName) const
Get the AlgorithmNode from by algorithm name using graph index.
GAUDI_API void setCurrentContext(const EventContext *ctx)
std::ostream & operator<<(std::ostream &s, const std::pair< T1, T2 > &p)
Serialize an std::pair in a python like format. E.g. "(1, 2)".
Struct to hold entries in the alg queues.
Class representing an event slot.
std::unique_ptr< EventContext > eventContext
Cache for the eventContext.
std::vector< EventSlot > allSubSlots
Actual sub-slot instances.
bool complete
Flags completion of the event.
void addSubSlot(std::unique_ptr< EventContext > viewContext, const std::string &nodeName)
Add a subslot to the slot (this constructs a new slot and registers it with the parent one).
void reset(EventContext *theeventContext)
Reset all resources in order to reuse the slot (thread-unsafe).
AlgsExecutionStates algsStates
Vector of algorithms states.
void disableSubSlots(const std::string &nodeName)
Disable event views for a given CF view node by registering an empty container Contact B.