4 Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
10 #include "GaudiKernel/MsgStream.h"
12 #include "AthenaBaseComps/AthMsgStreamMacros.h"
13 #include "TrigNavigation/TypeMaps.h"
14 #include "TrigNavStructure/BaseHolder.h"
16 #ifndef TrigNavigation_Holder_icc
17 #define TrigNavigation_Holder_icc
19 #define HOLDERLOG(logger,x) if (logger->msgLvl(MSG::x)) logger->msg() << MSG::x
23 std::string type_real_name() {
24 std::string name(__PRETTY_FUNCTION__);
25 size_t op = name.find('=');
26 size_t cl = name.find(']');
27 return name.substr(op+1, cl-op-1);
31 /////////////////////////////////////////////////////////////////////////////
32 // T is for objects, C for container for this objects
33 template<class STORED>
34 HLTNavDetails::Holder<STORED>::Holder() {
37 /////////////////////////////////////////////////////////////////////////////
38 template<class STORED>
39 HLTNavDetails::Holder<STORED>::Holder(const std::string& prefix, const std::string& label, uint16_t idx) :
40 IHolder(prefix, label, idx)
45 /////////////////////////////////////////////////////////////////////////////
46 namespace HLTNavDetails {
47 template<class STORED>
48 Holder<STORED>::~Holder() {
52 /////////////////////////////////////////////////////////////////////////////
53 template<class STORED, bool> struct createTemporary;
55 /////////////////////////////////////////////////////////////////////////////
56 template<class STORED>
57 struct createTemporary<STORED, true>
59 static STORED* do_it() {
60 STORED *s = new STORED;
61 s->clear(SG::VIEW_ELEMENTS);
66 /////////////////////////////////////////////////////////////////////////////
67 template<class STORED>
68 struct createTemporary<STORED, false>
70 static STORED* do_it() {
75 /////////////////////////////////////////////////////////////////////////////
76 template<class STORED>
77 template<class CONTAINER2>
78 bool HLTNavDetails::Holder<STORED>::get( ElementLinkVector<CONTAINER2>& el, HLT::TriggerElement::ObjectIndex idx) {
79 return static_cast<HolderImp<STORED, CONTAINER2>* >(this)->getElementLinks(el, idx);
82 /////////////////////////////////////////////////////////////////////////////
83 template<class STORED>
84 template<class CONTAINER2>
85 bool HLTNavDetails::Holder<STORED>::get( ElementLinkVector<CONTAINER2>& el ) {
86 return static_cast<HolderImp<STORED, CONTAINER2>* >(this)->getElementLinks(el);
90 /////////////////////////////////////////////////////////////////////////////
92 /////////////////////////////////////////////////////////////////////////////
93 template<class STORED, class CONTAINER>
94 HLTNavDetails::HolderImp<STORED, CONTAINER>::HolderImp()
98 /////////////////////////////////////////////////////////////////////////////
99 template<class STORED, class CONTAINER>
100 HLTNavDetails::HolderImp<STORED, CONTAINER>::HolderImp(const std::string& prefix, const std::string& label, uint16_t idx)
101 : Holder<STORED>(prefix, label, idx),
102 m_key (formatSGkey(prefix, ClassID_traits<CONTAINER>::typeName(), label))
106 /////////////////////////////////////////////////////////////////////////////
107 namespace HLTNavDetails {
108 template<class STORED, class CONTAINER>
109 HolderImp<STORED, CONTAINER>::~HolderImp() {
110 //typedef Holder<STORED> H;
111 // Don't touch m_log here --- if we're running global dtors, then
112 // it may have already been deleted.
118 /////////////////////////////////////////////////////////////////////////////
119 template<class STORED, class CONTAINER>
120 HLTNavDetails::IHolder* HLTNavDetails::HolderImp<STORED, CONTAINER>::clone(const std::string& prefix, const std::string& label, uint16_t idx ) const {
121 //typedef Holder<STORED> H;
122 if ( not m_containerProxy.empty() ) {
125 HolderImp<STORED, CONTAINER> *imp = new HolderImp<STORED, CONTAINER>(prefix, label, idx);
131 struct auxCLIDOrZero {
133 return ClassID_traits<AUX>::ID();
135 static std::string getName() {
136 return ClassID_traits<AUX>::typeName();
140 struct auxCLIDOrZero<HLT::TypeInformation::no_aux> {
144 static std::string getName() {
145 return std::string("no_aux");
149 /////////////////////////////////////////////////////////////////////////////
150 template<class STORED, class CONTAINER>
151 CLID HLTNavDetails::HolderImp<STORED, CONTAINER>::auxClidOrZero() const {
152 return auxCLIDOrZero<typename Container2Aux<CONTAINER>::type>::get();
155 /////////////////////////////////////////////////////////////////////////////
156 template<class STORED, class CONTAINER>
157 void HLTNavDetails::HolderImp<STORED, CONTAINER>::prepare(const asg::AsgMessaging& logger, HLT::AccessProxy* sg, IConversionSvc* conversionSvc, bool readonly){
158 typedef Holder<STORED> H;
159 IHolder::prepare(logger,sg,conversionSvc,readonly);
160 CLID auxCLID = auxCLIDOrZero<typename Container2Aux<CONTAINER>::type>::get();
164 ATH_MSG_INFO("HolderImp::prepare using a read-only proxy for aux store");
165 H::m_aux = new TypelessAuxProxy();
169 const auto itr = HLT::TypeMaps::proxies().find(auxCLID);
170 if ( itr == HLT::TypeMaps::proxies().end() ) {
171 ATH_MSG_ERROR("HolderImp::prepare can not find Aux store proxy " << *this);
175 H::m_aux = itr->second->clone();
176 if ( H::m_aux == 0 ) {
177 ATH_MSG_ERROR("HolderImp::prepare can not clone Aux store proxy " << *this);
179 ATH_MSG_VERBOSE("HolderImp::prepare proxy toAux store ready decorating");
185 /////////////////////////////////////////////////////////////////////////////
186 template<class STORED, class CONTAINER>
187 bool HLTNavDetails::HolderImp<STORED, CONTAINER>::syncWithSG(SG::OwnershipPolicy policy) {
188 ATH_MSG_DEBUG("HolderImp::syncWithSG policy " << policy);
189 typedef Holder<STORED> H;
190 if ( !H::m_storeGate ) {
191 ATH_MSG_WARNING("HolderImp::syncWithSG no SG available " << *this);
194 ATH_MSG_VERBOSE("HolderImp::syncWithSG syncing holder with SG " << *this);
196 const std::string auxkey = key()+"Aux.";
197 ATH_MSG_VERBOSE("HolderImp::syncWithSG looking in SG for key " << key() << " possible aux should have " << auxkey);
199 const bool transientInSG ( m_containerProxy.transientContains(H::m_storeGate, key() ) );
200 const bool persistentThroughSG ( m_containerProxy.contains(H::m_storeGate, key() ) );
201 if ( transientInSG or persistentThroughSG ) {
202 ATH_MSG_VERBOSE("HolderImp::syncWithSG objects "
203 << ( transientInSG ? "already in" : "available through" )
204 << " SG, syncing to them " << *this);
207 if ( m_containerProxy.sync( H::m_storeGate, key()).isFailure() ) {
208 ATH_MSG_WARNING("HolderImp::syncWithSG objects already in SG, however failed syncing (SG::retrieve) to them " << *this);
211 if( m_containerProxy.data()->ownPolicy() != SG::VIEW_ELEMENTS && H::m_aux && H::m_aux->sync(H::m_storeGate,auxkey).isFailure()){
212 ATH_MSG_WARNING("HolderImp::syncWithSG objects already in SG, however failed syncing (SG::retrieve) to aux store " << *this);
217 } else { // SG is empty, we need to put the obj into it
218 ATH_MSG_VERBOSE("HolderImp::syncWithSG objects not in SG, adding them to SG " << *this);
219 if ( m_containerProxy.create().isFailure() ) {
220 ATH_MSG_WARNING("HolderImp::syncWithSG can not create container " << *this);
224 auto defaultPolicy = m_containerProxy.data()->ownPolicy();
225 m_containerProxy.data()->clear( defaultPolicy == SG::VIEW_ELEMENTS ? SG::VIEW_ELEMENTS : policy);
228 CLID auxCLID = auxCLIDOrZero<typename Container2Aux<CONTAINER>::type>::get();
229 if ( auxCLID and policy != SG::VIEW_ELEMENTS ) {
230 if ( H::m_aux == 0 ) {
231 ATH_MSG_ERROR("HolderImp::syncWithSG can not clone Aux store proxy " << *this);
235 ATH_MSG_VERBOSE("HolderImp::syncWithSG proxy toAux store ready decorating");
237 if( H::m_aux->create().isFailure() ) {
238 ATH_MSG_WARNING("HolderImp::syncWithSG can not create Aux store for container " << *this);
242 if( H::m_aux->reg(H::m_storeGate,auxkey).isFailure() ) {
243 ATH_MSG_WARNING("HolderImp::syncWithSG can not register Aux store for container in SG " << *this);
247 SG::AuxVectorBase* container = m_containerProxy.castAuxVectorBase();
248 SG::IAuxStore* aux = H::m_aux->castIAuxStore();
249 if ( container and aux ) {
250 ATH_MSG_DEBUG("HolderImp::syncWithSG Aux sotore configured for " << *this);
251 container->setStore(aux);
253 ATH_MSG_WARNING("HolderImp::syncWithSG type configured to have Aux store but no appropriate Aux interfaces are implemented AuxVectorBase for container: "
254 << container << " IAuxStore for Aux sotore: " << aux << " "<< *this);
259 if ( m_containerProxy.reg( H::m_storeGate, key()).isFailure() ) {
260 ATH_MSG_ERROR("HolderImp::syncWithSG recording collection failed " << *this);
268 /////////////////////////////////////////////////////////////////////////////
269 template<class STORED, class CONTAINER>
270 bool HLTNavDetails::HolderImp<STORED, CONTAINER>::checkAndSetOwnership(SG::OwnershipPolicy policy) {
271 if ( m_containerProxy.empty() )
274 if ( m_containerProxy.data()->empty() ) {
275 m_containerProxy.data()->clear(policy);
279 if ( m_containerProxy.data()->ownPolicy() == policy )
284 /////////////////////////////////////////////////////////////////////////////
285 template<class CONTAINER, bool b>
286 struct transferBetweenContainers;
289 // case when the containers can be transfered
290 template <class CONTAINER>
291 struct transferBetweenContainers<CONTAINER, true> {
292 static void do_it(CONTAINER *source, CONTAINER* dest, const asg::AsgMessaging*) {
293 dest->insertMove (dest->end(), *source);
297 /////////////////////////////////////////////////////////////////////////////
298 // case when the containers CAN NOT be transfered
299 template <class CONTAINER>
300 struct transferBetweenContainers<CONTAINER, false> {
301 static void do_it(CONTAINER *, CONTAINER*, const asg::AsgMessaging*) {
302 throw std::runtime_error
303 ("TrigNavigation: Tried to attach an owning container of type " +
304 ClassName<CONTAINER>::name() +
305 "; only view containers of this type are supported.");
309 /////////////////////////////////////////////////////////////////////////////
310 // code below checks if the transfer of elements between the two OWNING containers can happen
311 // It is based on the check of the type returned by the iterator i.e. if the reference is const or not const (i.e. assignable)
313 template<class CONTAINER>
315 const static bool value = std::is_assignable<typename CONTAINER::iterator::reference,
316 typename CONTAINER::iterator::value_type>::value;
319 /////////////////////////////////////////////////////////////////////////////
320 template<class STORED, class CONTAINER, bool b> struct insert;
322 /////////////////////////////////////////////////////////////////////////////
323 // implementation if stored and container are the same
324 // this version is suggested by Attila, it has several advantages
325 // 1) the source container is useable after the insertion (important for the monitoring)
326 // 2) ownership of objects is greately simplified (i.e. the event-wise container always own objects,
327 // the roi-wise containers always view objects
329 template <class STORED, class CONTAINER>
330 struct insert<STORED, CONTAINER, true>{
331 static bool do_it(STORED *source, CONTAINER* dest, bool /*hasAux*/, const asg::AsgMessaging* log) {
333 HOLDERLOG(log, VERBOSE ) << "insert::do_it CONTAINER " << ClassID_traits<STORED>::typeName() << endmsg;
334 HOLDERLOG(log, VERBOSE ) << "Destination is " << (dest->ownPolicy() == SG::VIEW_ELEMENTS ? "VIEW" : "OWN")
335 << " source is " << (source->ownPolicy() == SG::VIEW_ELEMENTS ? "VIEW" : "OWN") << endmsg;
338 // - Input container is owning. Output container should also be owning;
339 // ownership should be transferred from input to output container.
341 // - Input is a view container and doesn't track indices
342 // (trackIndices() is false). Output should be a view container.
343 // Aux data are not transferred in this case.
345 // - Input is a view container that does track indices
346 // (trackIndices() is true). Output should be a view container
347 // with ALWAYS_TRACK_INDICES. Aux data are transferred in this case.
348 // (I don't think trigger will see this case.)
351 if ( dest->empty() ) { // empty destination, we can do adaptations
352 if ( source->ownPolicy() == SG::OWN_ELEMENTS ) {
353 dest->clear( SG::OWN_ELEMENTS );
356 if ( source->ownPolicy() == SG::VIEW_ELEMENTS and source->trackIndices() == false ) {
357 HOLDERLOG(log, VERBOSE ) << "insert::do_it destination container made a VIEW" << endmsg;
358 dest->setStore(static_cast<SG::IAuxStore*>(nullptr));
359 dest->clear( SG::VIEW_ELEMENTS);
362 if ( source->ownPolicy() == SG::VIEW_ELEMENTS and source->trackIndices() == true ) {
363 HOLDERLOG(log, VERBOSE ) << "insert::do_it destination container made a VIEW wiht indices tracking " << endmsg;
364 // it should be like this but I can not implemnt it like this because many container do not implement second arg dest->clear( SG::VIEW_ELEMENTS, SG::ALWAYS_TRACK_INDICES );
365 dest->clear( SG::VIEW_ELEMENTS );
368 if ( source->ownPolicy() != dest->ownPolicy() ) { // a simple check if in case of nonempty container we are dooing consistent insertion
369 HOLDERLOG(log, WARNING ) << "insert::do_it objects can not be inserted because of ownership issues. "
370 << "Destination container has already " << dest->size() << " objects "
371 << " and ownership policy "
372 << (dest->ownPolicy() == SG::OWN_ELEMENTS ? "OWN" : "") // this is dumb code but who knows what other policies will be implemented in the future
373 << (dest->ownPolicy() == SG::VIEW_ELEMENTS ? "VIEW" : "")
374 << " no action is performed, potential memory leak" << endmsg;
379 if ( source->ownPolicy() == SG::VIEW_ELEMENTS ) {
380 dest->insert(dest->end(), source->begin(), source->end());
381 HOLDERLOG(log, VERBOSE ) << "insert::do_it objects copied, conversion to view container not needed" << endmsg;
383 // We have an owning container. Transfer the element ownership
384 // from SOURCE to DEST. We can only do this if the container
385 // has modifiable iterators. For containers with non-modifiable
386 // iterators (like CaloTowerContainer), we throw an exception.
387 // Such containers should be added only as view containers.
388 transferBetweenContainers<CONTAINER, canTransfer<CONTAINER>::value>
389 ::do_it(source, dest, log);
397 /////////////////////////////////////////////////////////////////////////////
398 // implementation if stored and container are distinct
399 template <class STORED, class CONTAINER>
400 struct insert <STORED, CONTAINER, false>{
401 static bool do_it(STORED *s, CONTAINER* dest, bool /*hasAux*/, const asg::AsgMessaging*) {
407 /////////////////////////////////////////////////////////////////////////////
408 template<class STORED, class CONTAINER, bool b> struct remap;
409 template<class STORED, class CONTAINER>
410 struct remap<STORED, CONTAINER, false> {
411 static void do_it(const std::string&, const std::string&, STORED *, CONTAINER*, HLT::AccessProxy*, const asg::AsgMessaging*) {
416 /////////////////////////////////////////////////////////////////////////////
417 template<class STORED, class CONTAINER>
418 struct remap<STORED, CONTAINER, true> {
419 static void do_it(const std::string& storedkey , const std::string& contkey, STORED *s, CONTAINER* cont, HLT::AccessProxy *sg, const asg::AsgMessaging* log ) {
420 std::string skey = storedkey;
421 if ( storedkey == "" ) {
423 HOLDERLOG(log, VERBOSE) << "HolderImp::remap trying to discover object key, this is potentially slow and should be avoided, type: " << ClassID_traits<STORED>::typeName() << " from: " << s << " to: " << cont << endmsg;
424 SG::DataProxy* px = sg->proxy((void const* )s);
426 HOLDERLOG(log, WARNING) << "HolderImp::remap When remaping containers found no proxy for the object" << s << " of type " << ClassID_traits<STORED>::typeName() << endmsg;
429 if ( !px->isValid() ) {
430 HOLDERLOG(log, WARNING) << "HolderImp::remap When remaping containers found no valid proxy for the object" << s << " of type " << ClassID_traits<STORED>::typeName() << endmsg;
435 HOLDERLOG(log, VERBOSE) << "HolderImp::remap remapping collections of type: " << ClassID_traits<STORED>::typeName()
436 << " from: " << skey << " to: " << contkey << " while destination container size is: " << cont->size() << endmsg;
437 sg->remap(ClassID_traits<CONTAINER>::ID(), skey, contkey, cont->size());
441 template<class STORED, class CONTAINER, bool>
442 struct destinationOwnPolicy {};
444 template<class STORED, class CONTAINER>
445 struct destinationOwnPolicy<STORED, CONTAINER, false> {
446 static SG::OwnershipPolicy get(const STORED* /*source*/) {
447 return SG::OWN_ELEMENTS;
451 template<class STORED, class CONTAINER>
452 struct destinationOwnPolicy<STORED, CONTAINER, true> {
453 static SG::OwnershipPolicy get(const STORED* source) {
454 if ( source->ownPolicy() == SG::VIEW_ELEMENTS )
455 return SG::VIEW_ELEMENTS;
456 return SG::OWN_ELEMENTS;
462 /////////////////////////////////////////////////////////////////////////////
463 template<class STORED, class CONTAINER>
464 HLT::TriggerElement::ObjectIndex HLTNavDetails::HolderImp<STORED, CONTAINER>::add ATLAS_NOT_THREAD_SAFE ( const STORED* f_in, bool inSG, const std::string& sgKey ) {
466 // If insertMove is used, then the pointer being recorded cannot be const.
467 // Taking this object by const is anyway wrong because it will be modified
468 // (unless it's a view container).
469 STORED* f = const_cast<STORED*>(f_in);
470 typedef Holder<STORED> H;
472 if ( ! syncWithSG( destinationOwnPolicy<STORED, CONTAINER, std::is_same<STORED, CONTAINER>::value>::get(f) ) )
473 return HLT::TriggerElement::ObjectIndex();
475 uint32_t bidx = m_containerProxy.data()->size();
477 bool wasRecorded = false;
478 std::string thiskey(sgKey);
479 if ( !inSG && std::is_same<STORED, CONTAINER>::value ) { // conditions to place partial containers in SG
480 thiskey = this->getUniqueKey();
481 if ( H::m_storeGate->record(f, thiskey).isFailure() ) {
482 ATH_MSG_WARNING("HolderImp::add object " << f << "and sgKey:" << thiskey << " intended for holder" << *this << " can't be placed directly in SG");
486 ATH_MSG_VERBOSE("HolderImp::add feature SG direct registration succesful with the key:" << thiskey);
490 if ( inSG ) { //conditions to add remapping
491 remap<STORED, CONTAINER,
492 std::is_same<STORED, CONTAINER>::value>::do_it (thiskey, key(), f, m_containerProxy.data(), H::m_storeGate, H::m_logger);
495 bool insertStatus = insert<STORED, CONTAINER, std::is_same<STORED, CONTAINER>::value>
496 ::do_it (f, m_containerProxy.data(), H::m_aux != 0, H::m_logger);
497 if ( insertStatus == false ) {
498 ATH_MSG_WARNING("HolderImp::add insert failed " );
499 return HLT::TriggerElement::ObjectIndex();
502 uint32_t eidx = m_containerProxy.data()->size();
503 ATH_MSG_VERBOSE("HolderImp::add added object(s) to the container, size increase from : " << bidx << " to: " << eidx);
504 HLT::TriggerElement::ObjectIndex objIdx (H::subTypeIndex(), bidx, eidx );
506 m_memMgr.insert(std::make_pair(objIdx, MemoryMgr(f, inSG||m_containerProxy.data()->ownPolicy() == SG::OWN_ELEMENTS)));
509 if ( H::m_storeGate->setConst(f).isFailure() ) {
510 ATH_MSG_WARNING("HolderImp::add setConst failed " );
518 /////////////////////////////////////////////////////////////////////////////
519 template<class STORED, class CONTAINER, bool b> struct retrieve;
521 /////////////////////////////////////////////////////////////////////////////
522 // implementation if stored and container are the same
523 template <class STORED, class CONTAINER>
524 struct retrieve<STORED, CONTAINER, true>{
525 static bool do_it(const STORED*& dest, CONTAINER* src, HLT::TriggerElement::ObjectIndex idx) {
527 if ( src->size() < idx.objectsBegin() || src->size() < idx.objectsEnd()) {
528 REPORT_MESSAGE_WITH_CONTEXT(MSG::VERBOSE,"Holder") << "either begin index or end index is larger than size";
529 REPORT_MESSAGE_WITH_CONTEXT(MSG::VERBOSE,"Holder") << "size: " << src->size() << " begin: " << idx.objectsBegin() << " end: " << idx.objectsEnd();
533 dest = createTemporary<STORED, std::is_same<STORED, CONTAINER>::value>::do_it();
534 typename CONTAINER::iterator beg = src->begin();
535 typename CONTAINER::iterator end = src->begin();
536 std::advance(beg, idx.objectsBegin());
537 std::advance(end, idx.objectsEnd());
539 // get(Feature) should really not be taking a const reference for the case
540 // where STORED!=CONTAINER as we do have to modify the destination. But the
541 // user is responsible for not filling the same container concurrently anyway.
542 auto nonconst_dest ATLAS_THREAD_SAFE = const_cast<STORED*&>(dest);
543 nonconst_dest->insert(nonconst_dest->end(), beg, end);
548 /////////////////////////////////////////////////////////////////////////////
549 // implementation if stored and container are distinct
550 template <class STORED, class CONTAINER>
551 struct retrieve <STORED, CONTAINER, false>{
552 static bool do_it(const STORED*& dest, CONTAINER* src, HLT::TriggerElement::ObjectIndex idx) {
554 if (idx.objectsBegin() < (*src).size()) {
555 dest = src->at(idx.objectsBegin());
564 template<class STORED, class CONTAINER>
565 bool HLTNavDetails::HolderImp<STORED, CONTAINER>::getWithLink(typename set_link<STORED,CONTAINER,std::is_same<STORED,CONTAINER>::value>::type& link,
566 HLT::TriggerElement::ObjectIndex& idx) {
568 const STORED* dest = 0;
569 bool result = this->get(dest,idx);
570 if(!result) return false;
572 link = set_link<STORED,CONTAINER,std::is_same<STORED,CONTAINER>::value>::do_it(dest,m_containerProxy.data(),idx);
576 /////////////////////////////////////////////////////////////////////////////
577 template<class STORED, class CONTAINER>
578 bool HLTNavDetails::HolderImp<STORED, CONTAINER>::get(const STORED*& dest, HLT::TriggerElement::ObjectIndex idx) {
579 typedef Holder<STORED> H;
584 ATH_MSG_VERBOSE("HolderImp::get getting object(s) from Holder" << *this);
585 typename MemoryMgrMap::const_iterator cache;
586 if ( (cache = m_memMgr.find(idx)) != m_memMgr.end() ) {
587 ATH_MSG_DEBUG("HolderImp::get object found in the cache with address " << idx);
588 dest = cache->second.proxy.data();
592 ATH_MSG_VERBOSE("HolderImp::get getting object from primary collection " << idx);
595 if ( ! retrieve<STORED, CONTAINER, // short circuited .. retrieve will not run if in cache
596 std::is_same<STORED, CONTAINER>::value>::
597 do_it (dest, m_containerProxy.data(), idx) ) {
598 ATH_MSG_WARNING("HolderImp::get getting chunk of the container failed for Holder: " << *this
599 << " index: " << idx);
603 if ( std::is_same<STORED, CONTAINER>::value ) { // temporary view containers in SG and cache filling
605 // We don't have an implementation of FeatureProxy that takes a const reference.
606 // But this should be safe (modulo the comments in the do_it method above).
607 auto nonconst_dest ATLAS_THREAD_SAFE = const_cast<STORED*&>(dest);
608 FeatureProxy tempProxy( nonconst_dest );
610 m_memMgr.insert(std::make_pair(idx, MemoryMgr(tempProxy, true))); // store it in the cache for futher uses
612 std::string sgKey = this->generateAliasKey(this->typeClid(), this->subTypeIndex(), this->label(), 0xffffffff );
614 if ( tempProxy.reg(H::m_storeGate, sgKey).isFailure() ) {
615 ATH_MSG_WARNING("HolderImp::get for some reason object can't be placed in SG, key:" << sgKey);
618 remap<STORED, CONTAINER,
619 std::is_same<STORED, CONTAINER>::value>::do_it (sgKey, key(), tempProxy.data(), m_containerProxy.data(), H::m_storeGate, H::m_logger);
620 ATH_MSG_VERBOSE("Added view collection to SG with defined EL remapping to event-wide colection, key: " << sgKey);
626 /////////////////////////////////////////////////////////////////////////////
627 // check if objects in obj are in the container
628 template<class STORED, class CONTAINER, bool b> struct isin;
630 /////////////////////////////////////////////////////////////////////////////
631 // check if the container obj is a subcontainer of cont
632 template <class STORED, class CONTAINER>
633 struct isin<STORED, CONTAINER, true> {
634 static bool do_it(const STORED* obj, const CONTAINER* cont, const asg::AsgMessaging*, uint32_t& begin, uint32_t& end) {
635 typename CONTAINER::const_iterator it = std::search(cont->begin(), cont->end(), obj->begin(), obj->end());
636 if ( it == cont->end() ) {
639 begin = it - cont->begin();
640 end = begin + obj->size();
645 /////////////////////////////////////////////////////////////////////////////
646 // check if the obj is in a container cont
647 template <class STORED, class CONTAINER>
648 struct isin<STORED, CONTAINER, false> {
649 static bool do_it(const STORED* obj, const CONTAINER* cont, const asg::AsgMessaging*, uint32_t& begin, uint32_t& end) {
650 typename CONTAINER::const_iterator it = std::find(cont->begin(), cont->end(), obj);
651 if ( it == cont->end() ) {
654 begin = it - cont->begin();
661 template<class STORED, class CONTAINER>
662 bool HLTNavDetails::HolderImp<STORED, CONTAINER>::contains(const STORED* obj, HLT::TriggerElement::ObjectIndex& idx) {
663 typedef Holder<STORED> H;
667 ATH_MSG_VERBOSE("HolderImp::contains");
670 bool ok = isin<STORED, CONTAINER,
671 std::is_same<STORED, CONTAINER>::value>::do_it (obj, m_containerProxy.data(), H::m_logger, begin, end);
673 ATH_MSG_VERBOSE("HolderImp::contains object " << obj << " not in the holder" << *this );
676 idx = HLT::TriggerElement::ObjectIndex(H::subTypeIndex(),begin,end);
677 ATH_MSG_VERBOSE("HolderImp::contains object " << obj << " found by in holder" << *this << " " << idx);
681 /////////////////////////////////////////////////////////////////////////////
682 template<class STORED, class CONTAINER>
683 bool HLTNavDetails::HolderImp<STORED, CONTAINER>::getElementLinks(ElementLinkVector<CONTAINER>& cont,
684 HLT::TriggerElement::ObjectIndex idx) {
685 //typedef Holder<STORED> H;
689 ATH_MSG_VERBOSE("HolderImp::getElementLinks(ELV, Index) getting objects");
690 for (unsigned i = idx.objectsBegin(); i != idx.objectsEnd(); ++i ){
691 cont.push_back(ElementLink<CONTAINER>(*(m_containerProxy.data()), i));
696 /////////////////////////////////////////////////////////////////////////////
697 template<class STORED, class CONTAINER>
698 bool HLTNavDetails::HolderImp<STORED, CONTAINER>::getElementLinks(ElementLinkVector<CONTAINER>& cont) {
700 //typedef Holder<STORED> H;
703 ATH_MSG_VERBOSE("HolderImp::getElementLinks (ELV) getting all objects");
704 for (unsigned i = 0; i < m_containerProxy.data()->size(); ++i ){
705 cont.push_back(ElementLink<CONTAINER>(*(m_containerProxy.data()), i));
710 /////////////////////////////////////////////////////////////////////////////
711 template<class STORED, class CONTAINER>
712 std::string HLTNavDetails::HolderImp<STORED, CONTAINER>::getUniqueKey() {
713 ATH_MSG_VERBOSE("HolderImp::getUniqueKey");
716 return IHolder::generateAliasKey( this->typeClid(), this->subTypeIndex(), this->label(),
717 m_containerProxy.data()->size() );
720 template<class STORED, class CONTAINER>
721 std::string HLTNavDetails::HolderImp<STORED, CONTAINER>::getNextKey() {
722 ATH_MSG_VERBOSE("HolderImp::getNextKey");
723 return getUniqueKey();
729 /////////////////////////////////////////////////////////////////////////////
730 template<class STORED, class CONTAINER>
731 bool HLTNavDetails::HolderImp<STORED, CONTAINER>::serialize(std::vector<uint32_t>& output) const {
732 typedef Holder<STORED> H; // this is to make things below shorter
734 ATH_MSG_VERBOSE("HolderImp::serialize " << *this);
735 // if feature to be forgotten then indication of it is simply 0 size of serialized vector
736 H::serialize(output);
741 /////////////////////////////////////////////////////////////////////////////
742 template<class STORED, class CONTAINER>
743 void HLTNavDetails::HolderImp<STORED, CONTAINER>::print(MsgStream& m) const {
745 if ( not m_containerProxy.empty() )
746 m << " size: " << m_containerProxy.data()->size() << " @"<<m_containerProxy.data();
748 m << " container not allocated yet";
751 /////////////////////////////////////////////////////////////////////////////
752 template<class STORED, class CONTAINER>
753 DataObject* HLTNavDetails::HolderImp<STORED, CONTAINER>::getDataObject() {
754 if(!m_containerProxy.data()) return 0;
755 return SG::asStorable(m_containerProxy.data());
758 #define _IS_AUXTYPE_ !std::is_same<typename Container2Aux<T>::type,HLT::TypeInformation::no_aux>::value
760 struct AuxDataObjectHelper{
762 static typename std::enable_if<!_IS_AUXTYPE_,DataObject*>::type get(HLTNavDetails::ITypeProxy*/* aux*/){
766 static typename std::enable_if<_IS_AUXTYPE_,DataObject*>::type get(HLTNavDetails::ITypeProxy* aux){
767 typedef typename Container2Aux<T>::type auxtype;
768 HLTNavDetails::TypeProxy<auxtype>* auxcasted = static_cast<HLTNavDetails::TypeProxy<auxtype>*>(aux);
770 if(!auxcasted->data()) return 0;
771 return SG::asStorable(auxcasted->data());
776 static typename std::enable_if<!_IS_AUXTYPE_,bool>::type set(HLTNavDetails::ITypeProxy*,DataObject*){
777 return true;//always success
780 static typename std::enable_if<_IS_AUXTYPE_,bool>::type set(HLTNavDetails::ITypeProxy* aux, DataObject* dobjaux){
781 typedef typename Container2Aux<T>::type auxtype;
782 HLTNavDetails::TypeProxy<auxtype>* auxcasted = static_cast<HLTNavDetails::TypeProxy<auxtype>*>(aux);
784 bool success = SG::fromStorable(dobjaux,auxcasted->data_ref());
785 auxcasted->syncTypeless();
786 REPORT_MESSAGE_WITH_CONTEXT(MSG::VERBOSE,"Holder") << "set from storable " << success << " to address " << auxcasted->data() << std::endl;
793 template<class STORED, class CONTAINER>
794 DataObject* HLTNavDetails::HolderImp<STORED, CONTAINER>::getAuxDataObject() {
795 return AuxDataObjectHelper::get<CONTAINER>(this->m_aux);
798 template<class STORED, class CONTAINER>
799 bool HLTNavDetails::HolderImp<STORED, CONTAINER>::setAuxDataObject(DataObject* dobjaux) {
800 bool status = AuxDataObjectHelper::set<CONTAINER>(this->m_aux,dobjaux);
801 ATH_MSG_VERBOSE("container data is: " << m_containerProxy.data());
802 SG::AuxVectorBase* container = m_containerProxy.castAuxVectorBase();
803 if(!this->m_aux or !container){
804 ATH_MSG_ERROR("in aux branch but aux type proxy or container proxy is null");
805 ATH_MSG_ERROR("container is: " << container);
806 ATH_MSG_ERROR("aux is: " << this->m_aux);
809 SG::IAuxStore* aux = this->m_aux->castIAuxStore();
811 ATH_MSG_ERROR("cast of auxstore failed");
813 if(container and aux and status){
814 ATH_MSG_VERBOSE("container is: " << container);
815 ATH_MSG_VERBOSE("aux is: " << this->m_aux);
816 container->setStore(aux);
819 ATH_MSG_WARNING("something went wrong setting aux data object");
824 /////////////////////////////////////////////////////////////////////////////
825 template<class STORED, class CONTAINER>
826 bool HLTNavDetails::HolderImp<STORED, CONTAINER>::setDataObject(DataObject* dobj) {
827 bool success = SG::fromStorable(dobj, m_containerProxy.data_ref());
828 m_containerProxy.syncTypeless();
829 REPORT_MESSAGE_WITH_CONTEXT(MSG::VERBOSE,"Holder") << "set from storable " << success << " to address " << m_containerProxy.data();
833 /////////////////////////////////////////////////////////////////////////////
834 template<class STORED, class CONTAINER>
835 HLTNavDetails::HolderImp<STORED, CONTAINER>::MemoryMgr::MemoryMgr(const FeatureProxy& st, bool sg)
836 : proxy(st), inSG(sg)
839 /////////////////////////////////////////////////////////////////////////////
840 template<class STORED, class CONTAINER>
841 HLTNavDetails::HolderImp<STORED, CONTAINER>::MemoryMgr::MemoryMgr()
845 /////////////////////////////////////////////////////////////////////////////
846 template<class STORED, class CONTAINER>
847 void HLTNavDetails::HolderImp<STORED, CONTAINER>::MemoryMgr::clear() {
848 // if the thing is not in SG it shoudl not be cleared, if is the SG will take care of it if ( !inSG ) proxy.clear();
851 /////////////////////////////////////////////////////////////////////////////
852 template<class STORED>
853 MsgStream& HLTNavDetails::operator<< ( MsgStream& m, const HLTNavDetails::Holder<STORED>& h ) {
858 /////////////////////////////////////////////////////////////////////////////
859 template<class STORED, class CONTAINER>
860 MsgStream& HLTNavDetails::operator<< ( MsgStream& m, const HLTNavDetails::HolderImp<STORED, CONTAINER>& h ) {