ATLAS Offline Software
Loading...
Searching...
No Matches
Ath::DynamicDataHelper Class Reference

Helper class to gather all declared data IDs and propagate them to components which declare data dependencies dynamically. More...

#include <DynamicDataHelper.h>

Collaboration diagram for Ath::DynamicDataHelper:

Public Member Functions

void gatherDataHandlesAndDynamicConsumers (const std::string &parent_name, Gaudi::Algorithm *theAlgorithm)
 Gather the input and output data declared by the given algorithm, its child algorithms and their tools.
StatusCode addExtraDependencies (IClassIDSvc &clid_svc, std::vector< std::string > &undeclared_output_data, MsgStream &out)
 Add extra output data which is not declared by any of the gathered components.
void updateDataNeeds (unsigned int max_pass, MsgStream &out)
 Update the data dependencies of all components which dynamically declare tehm.

Protected Member Functions

bool updateDataNeeds (const std::vector< const DataObjID * > &input_data_in, const std::vector< const DataObjID * > &output_data_in, std::vector< const DataObjID * > &input_data_out, std::vector< const DataObjID * > &output_data_out, MsgStream &out)
 Update the data dependencies of all components once.

Protected Attributes

std::vector< DataObjID > m_extraOutputIDs
DataObjIDPtrColl m_inputHandles
DataObjIDPtrColl m_outputHandles
std::unordered_map< IDynamicDataConsumer *, std::vector< Gaudi::Algorithm * > > m_dynDataConsumer

Detailed Description

Helper class to gather all declared data IDs and propagate them to components which declare data dependencies dynamically.

Definition at line 25 of file DynamicDataHelper.h.

Member Function Documentation

◆ addExtraDependencies()

StatusCode Ath::DynamicDataHelper::addExtraDependencies ( IClassIDSvc & clid_svc,
std::vector< std::string > & undeclared_output_data,
MsgStream & out )

Add extra output data which is not declared by any of the gathered components.

Parameters
clid_svcthe ClassIDSvc needed to translate the type name into a CLID.
undeclared_output_datastrings which are composed of the type and variable name separated by "/".
outthe message output stream used for error messages.

Definition at line 26 of file DynamicDataHelper.cxx.

26 {
27 std::stringstream error;
28 if (!m_extraOutputIDs.empty()) {
29 out << MSG::FATAL << "Logic erroor. Already added some extra output data IDs. This method can only be called once." << endmsg;
30 return StatusCode::FAILURE;
31 }
32 m_extraOutputIDs.reserve( undeclared_output_data.size() );
33 for(const std::string &type_and_name : undeclared_output_data) {
34 std::string::size_type pos = type_and_name.find('/');
35 if (pos == std::string::npos) {
36 error << " " << type_and_name;
37 }
38 else {
39 std::string_view type_name(type_and_name.data(), pos);
40 std::string_view var_name(&(type_and_name.data()[pos+1]), type_and_name.size()-pos-1);
41 CLID clid;
42 if (clid_svc.getIDOfTypeName(std::string(type_name), clid).isFailure() ) {
43 // out << MSG::FATAL << " Failed to get CLID for " << type_name << endmsg;
44 // return StatusCode::FAILURE;
45 error << " no clid: " << type_name;
46 }
47 else {
48 m_extraOutputIDs.push_back( DataObjID(clid, std::string(var_name)) );
49 if (msgLvl(out,MSG::VERBOSE)) {
50 out << MSG::VERBOSE << "DEBUG add extra dependency " << type_name << " / " << var_name << " -> " << clid << endmsg;
51 }
52 }
53 }
54 }
55 if (!error.str().empty()) {
56 out << MSG::FATAL << "Invaid alements in property " << error.str().c_str() << endmsg;
57 return StatusCode::FAILURE;
58 }
59 for (const DataObjID &id : m_extraOutputIDs ) {
60 m_outputHandles.insert( &id );
61 }
62 return StatusCode::SUCCESS;
63 }
#define endmsg
uint32_t CLID
The Class ID type.
std::vector< DataObjID > m_extraOutputIDs
DataObjIDPtrColl m_outputHandles

◆ gatherDataHandlesAndDynamicConsumers()

void Ath::DynamicDataHelper::gatherDataHandlesAndDynamicConsumers ( const std::string & parent_name,
Gaudi::Algorithm * theAlgorithm )

Gather the input and output data declared by the given algorithm, its child algorithms and their tools.

Parameters
parent_namethe name of the parent component used in messsages
theAlgorithmthe top algorithm to start the collection Additionally also all components are collected which dynamically declare their data dependencies.

Definition at line 65 of file DynamicDataHelper.cxx.

65 {
66 // |> debugging
67 auto algorithm_visitor =
68 [this](Gaudi::Algorithm *an_alg) {
69 IDynamicDataConsumer *a_dyn_data_consumer=dynamic_cast<IDynamicDataConsumer *>(an_alg);
70 if (a_dyn_data_consumer) {
71 std::vector<Gaudi::Algorithm *> &alg_list = m_dynDataConsumer[a_dyn_data_consumer];
72 if (std::find(alg_list.begin(),alg_list.end(),an_alg)==alg_list.end()) {
73 alg_list.push_back(an_alg);
74 }
75 }
76 // have to collect input and output handles because the sequence will only collect them after initialize
77 insertHandles(m_inputHandles, an_alg->inputHandles());
78 insertHandles(m_outputHandles, an_alg->outputHandles());
79 std::vector<IAlgTool *> &tools ATLAS_THREAD_SAFE
80 = const_cast< std::vector<IAlgTool *> &>(const_cast<const Gaudi::Algorithm *>(an_alg)->tools());
81 // |> debugging
82 auto tool_visitor = [this, an_alg](IAlgTool *alg_tool) {
83 IDynamicDataConsumer *a_dyn_data_consumer=dynamic_cast<IDynamicDataConsumer *>(alg_tool);
84 if (a_dyn_data_consumer) {
85 std::vector<Gaudi::Algorithm *> &alg_list = m_dynDataConsumer[a_dyn_data_consumer];
86 if (std::find(alg_list.begin(),alg_list.end(),an_alg)==alg_list.end()) {
87 alg_list.push_back(an_alg);
88 }
89 }
90 if (auto* tool_impl = dynamic_cast<AlgTool*>( alg_tool ); tool_impl) {
91 insertHandles(m_inputHandles, tool_impl->inputHandles());
92 insertHandles(m_outputHandles, tool_impl->outputHandles());
93 }
94 };
95 xGaudi::ToolVisitor::visit( tools,tool_visitor);
96 };
97 xGaudi::AlgorithmVisitor::visit({theAlgorithm},algorithm_visitor);
98 }
#define ATLAS_THREAD_SAFE
DataObjIDPtrColl m_inputHandles
std::unordered_map< IDynamicDataConsumer *, std::vector< Gaudi::Algorithm * > > m_dynDataConsumer

◆ updateDataNeeds() [1/2]

bool Ath::DynamicDataHelper::updateDataNeeds ( const std::vector< const DataObjID * > & input_data_in,
const std::vector< const DataObjID * > & output_data_in,
std::vector< const DataObjID * > & input_data_out,
std::vector< const DataObjID * > & output_data_out,
MsgStream & out )
protected

Update the data dependencies of all components once.

Parameters
input_data_inIDs of all declared input data
output_data_inIDs of all declared output data
input_data_outIDs of newly declared input data in this iteration
output_data_outIDs of newly declared input data in this iteration
Returns
true if new input or output data was declared.

Definition at line 121 of file DynamicDataHelper.cxx.

125 {
126 bool updated=false;
127 if (msgLvl(out,MSG::VERBOSE)) {
128 out<< MSG::VERBOSE << " inputs:";
129 for (const DataObjID *id : input_data_in) {
130 out << " " << *id ;
131 }
132 out << endmsg;
133 out << MSG::VERBOSE << " outputs:";
134 for (const DataObjID *id : output_data_in) {
135 out << " " << *id ;
136 }
137 out << endmsg;
138 }
139 for (std::pair<IDynamicDataConsumer * const,std::vector<Gaudi::Algorithm *> > &dyn_data_consumer : m_dynDataConsumer ) {
140 std::vector<Gaudi::DataHandle *> tmp_new_input_handles;
141 std::vector<Gaudi::DataHandle *> tmp_new_output_handles;
142 bool ret = dyn_data_consumer.first->updateDataNeeds(input_data_in, output_data_in, tmp_new_input_handles, tmp_new_output_handles);
143 if (msgLvl(out,MSG::VERBOSE)) {
144 out << MSG::VERBOSE << " new data for";
145 for (const Gaudi::Algorithm *parent_alg : dyn_data_consumer.second) {
146 out << " " << parent_alg->name();
147 }
148 out << " i:" << tmp_new_input_handles.size()
149 << " o:" << tmp_new_output_handles.size()
150 << endmsg;
151 }
152 updated |= ret;
153 if (ret) {
154 if (msgLvl(out,MSG::DEBUG)) {
155 if (Gaudi::Algorithm * const an_alg = dynamic_cast<Gaudi::Algorithm * const>(dyn_data_consumer.first); an_alg) {
156 out << MSG::DEBUG << an_alg->name() << " updated its data needs." << endmsg;
157 // DEBUG:
158 out << MSG::DEBUG << an_alg->name() << " inputs:";
159 for (const Gaudi::DataHandle *handle : an_alg->inputHandles()) {
160 out << " " << handle->fullKey();
161 }
162 out << endmsg;
163 }
164 else if (AlgTool *alg_tool = dynamic_cast<AlgTool * const>(dyn_data_consumer.first); alg_tool) {
165 out << MSG::DEBUG << alg_tool->name() << " updated its data needs." << endmsg;
166 // DEBUG:
167 out << MSG::DEBUG << alg_tool->name() << " inputs:";
168 for (const Gaudi::DataHandle *handle : alg_tool->inputHandles()) {
169 out << " " << handle->fullKey();
170 }
171 out << endmsg;
172 }
173 else {
174 out << MSG::WARNING << "Unknown dynamic data consumer type " << typeid(dyn_data_consumer.first).name() << endmsg;
175 }
176 }
177 }
178 for (Gaudi::Algorithm *parent_alg : dyn_data_consumer.second) {
179 input_data_out.reserve(input_data_out.size()+tmp_new_input_handles.size());
180 for (Gaudi::DataHandle *a_handle : tmp_new_input_handles) {
181 parent_alg->addDependency(a_handle->fullKey(), Gaudi::DataHandle::Reader);
182 input_data_out.push_back(&(a_handle->fullKey()));
183 if (msgLvl(out,MSG::DEBUG)) out << MSG::DEBUG << " addDependency new input for " << parent_alg->name() << " "
184 << a_handle->fullKey().className() << " / " << a_handle->objKey() << endmsg;
185 }
186 output_data_out.reserve(output_data_out.size()+tmp_new_output_handles.size());
187 for (Gaudi::DataHandle *a_handle : tmp_new_output_handles) {
188 parent_alg->addDependency(a_handle->fullKey(), Gaudi::DataHandle::Writer);
189 output_data_out.push_back(&(a_handle->fullKey()));
190 if (msgLvl(out,MSG::DEBUG)) out << MSG::DEBUG << " addDependency new output for " << parent_alg->name() << " "
191 << a_handle->fullKey().className() << " / " << a_handle->objKey() << endmsg;
192 }
193 }
194 }
195 return updated;
196 }
bool const RAWDATA *ch2 const

◆ updateDataNeeds() [2/2]

void Ath::DynamicDataHelper::updateDataNeeds ( unsigned int max_pass,
MsgStream & out )

Update the data dependencies of all components which dynamically declare tehm.

Parameters
max_passmaximum number of iterations
outthe message stream of the parent component The update happens iteratively until non of the components declares new output data, but at most max_pass times.

Definition at line 100 of file DynamicDataHelper.cxx.

101 {
102 if (msgLvl(out,MSG::VERBOSE)) out << MSG::VERBOSE << "Allow dynamic data consumers to update their data dependencies." << endmsg;
103 std::vector<const DataObjID *> all_input_data;
104 std::vector<const DataObjID *> all_output_data;
105 all_input_data.insert( all_input_data.end(), m_inputHandles.begin(), m_inputHandles.end());
106 all_output_data.insert( all_output_data.end(), m_outputHandles.begin(), m_outputHandles.end());
107
108 std::vector<const DataObjID *> new_input_data;
109 std::vector<const DataObjID *> new_output_data;
110 unsigned int pass_i=max_pass;
111 unsigned last_out_size=new_output_data.size();
112 for (; --pass_i>0 && updateDataNeeds(all_input_data, all_output_data, new_input_data, new_output_data,out); ) {
113 if (last_out_size == new_output_data.size() ) break;
114 last_out_size=new_output_data.size();
115 };
116 if (last_out_size != new_output_data.size()) {
117 out << MSG::WARNING << "Not iterating any further, although after " << max_pass << " iterations there are still algorithms which updated their data needs. " << endmsg;
118 }
119 }
void updateDataNeeds(unsigned int max_pass, MsgStream &out)
Update the data dependencies of all components which dynamically declare tehm.

Member Data Documentation

◆ m_dynDataConsumer

std::unordered_map< IDynamicDataConsumer *,std::vector<Gaudi::Algorithm *> > Ath::DynamicDataHelper::m_dynDataConsumer
protected

Definition at line 69 of file DynamicDataHelper.h.

◆ m_extraOutputIDs

std::vector<DataObjID> Ath::DynamicDataHelper::m_extraOutputIDs
protected

Definition at line 65 of file DynamicDataHelper.h.

◆ m_inputHandles

DataObjIDPtrColl Ath::DynamicDataHelper::m_inputHandles
protected

Definition at line 66 of file DynamicDataHelper.h.

◆ m_outputHandles

DataObjIDPtrColl Ath::DynamicDataHelper::m_outputHandles
protected

Definition at line 67 of file DynamicDataHelper.h.


The documentation for this class was generated from the following files: