Skip to content
Snippets Groups Projects
Commit 249ccdeb authored by Christoph Hasse's avatar Christoph Hasse :cartwheel_tone1:
Browse files

make Functor DataHandles work with late binding in `start()`, see LHCb!3430

parent 94c7b3c2
No related branches found
No related tags found
1 merge request!2699FunctorFactory, replace CLING backend with native compiler
......@@ -112,7 +112,39 @@ namespace Functors::detail {
void bind_helper( Algorithm* alg, std::index_sequence<Is...> ) {
static_assert( std::is_base_of_v<IDataHandleHolder, Algorithm>,
"You must include the full declaration of the owning algorithm type!" );
( std::get<Is>( m_handles ).emplace( m_tes_locs[Is], alg ), ... );
if ( alg->msgLevel( MSG::DEBUG ) ) {
alg->info() << "Init of DataHandles of Functor (" + get_name( m_f ) + "):" << endmsg;
}
( init_data_handle( std::get<Is>( m_handles ).emplace( m_tes_locs[Is], alg ), alg ), ... );
}
/**
* @brief Initialize a TES DataHandle and check that the owning algorithm
* was configured correctly and already holds our input in ExtraInputs
*
* For more info on the logic please see the detailed explanation of how
* Functors obtain their data dependencies in FIXME(Link to where?)
*
* @param handle This handle will be initialized
* @param alg Algorithm/Tool which owns this functor
*/
template <typename T, typename Algorithm>
void init_data_handle( DataObjectReadHandle<T>& handle, Algorithm* alg ) {
if ( alg->msgLevel( MSG::DEBUG ) ) { alg->info() << " + Init of DataHandle " << handle.objKey() << endmsg; }
if ( alg->extraInputDeps().count( handle.objKey() ) == 0 ) {
throw GaudiException{"Usage of DataHandle[\"" + handle.objKey() + "\"] in Functor (" + get_name( m_f ) +
") requires that owning algorithm " + alg->name() +
" contains this TES location inside the ExtraInputs property. This is likely a "
"Configuration/PyConf bug!",
get_name( m_f ), StatusCode::FAILURE};
}
// DataObjectReadHandle has a protected `init()` so we need to call it
// through it's base class. This is the same thing Gaudi::Algorithm does in
// sysInitialize()
static_cast<Gaudi::DataHandle*>( &handle )->init();
}
/** Make a tuple of references to the result of dereferencing each
......
......@@ -114,6 +114,10 @@ struct FunctorFactory : public extends<Service, Functors::IFactory> {
if ( msgLevel( MSG::VERBOSE ) ) { verbose() << "Full code to compile is:\n" << full_code << endmsg; }
// FIXME We should extend this to somehow include the hash of the
// precompiled header, otherwise library reusing is a bit of a dangerous
// game during development as you need to remember to delete the *.so
// objects
auto const file_prefix =
m_jit_lib_dir + "FunctorJitLib_" + Functors::Cache::hashToStr( Functors::Cache::makeHash( full_code ) );
auto const lib_filename = file_prefix + ".so";
......@@ -132,7 +136,7 @@ struct FunctorFactory : public extends<Service, Functors::IFactory> {
info() << "Reusing functor library: " << lib_filename << endmsg;
} else {
auto const cpp_filename = file_prefix + ".cpp";
info() << "New functor library will be created based generated C++ file: " << cpp_filename << endmsg;
info() << "New functor library will be created with generated C++ file: " << cpp_filename << endmsg;
{
std::ofstream out( cpp_filename );
out << full_code;
......
......@@ -14,9 +14,6 @@ namespace std {
std::ostream& operator<<( std::ostream& o, ThOr::FunctorDesc const& f ) {
using GaudiUtils::operator<<;
return o << "\"(" << std::quoted( f.code, '\'' ) << ", "
<< ", " << f.headers
<< ", " << std::quoted( f.repr, '\'' )
<< ")\""
;
<< ", " << f.headers << ", " << std::quoted( f.repr, '\'' ) << ")\"";
}
} // namespace std
###############################################################################
# (c) Copyright 2019 CERN for the benefit of the LHCb Collaboration #
# #
# This software is distributed under the terms of the GNU General Public #
# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". #
# #
# In applying this licence, CERN does not waive the privileges and immunities #
# granted to it by virtue of its status as an Intergovernmental Organization #
# or submit itself to any jurisdiction. #
###############################################################################
from Gaudi.Configuration import ApplicationMgr, VERBOSE
from Configurables import Gaudi__Monitoring__MessageSvcSink as MessageSvcSink
from Configurables import EvtStoreSvc
from Functors import SIZE
# algorithms are coming from PyConf because we need to use DataHandles etc.
from PyConf.Algorithms import FunctorExampleAlg as FEA, Gaudi__Examples__VectorDataProducer as VDP
from PyConf.dataflow import dataflow_config
app = ApplicationMgr(OutputLevel=VERBOSE)
# FEA has counters so we need a sink
app.ExtSvc.append(MessageSvcSink())
# why does the default EventDataSvc not work? good question!!!
# FIXME make an issue for that
whiteboard = EvtStoreSvc("EventDataSvc", EventSlots=1)
app.ExtSvc.append(whiteboard)
vdp = VDP(name="VDP")
fea = FEA(name="FEA", Cut=SIZE(vdp.OutputLocation) < 5, OutputLevel=VERBOSE)
# FIXME
# make a test out of the below, which works in pyconf as long as we allow strings as DataHandles...
# fea = FEA(name="FEA", Cut=SIZE(vdp.OutputLocation.location) < 5, OutputLevel=VERBOSE)
# But is correctly caught on the C++ side and throws:
# ERROR TES::Size Usage of DataHandle["/Event/VDP/OutputLocation"] in Functor (TES::Size) requires that
# owning algorithm FEA contains this TES location inside the ExtraInputs property. This is likely a Configuration/PyConf bug!
c = dataflow_config()
c.update(fea.configuration())
algs, _ = c.apply()
app.TopAlg = algs
# - Event
app.EvtMax = 1
app.EvtSel = "NONE"
app.HistogramPersistency = "NONE"
# FIXME
# 1. Add another test like the above with the HLTScheduler to show/test that algs get scheduled correctly
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment