ATLAS Offline Software
Loading...
Searching...
No Matches
Holder.icc
Go to the documentation of this file.
1// Emacs -*- c++ -*-
2
3/*
4 Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
5*/
6
7#include <iterator>
8#include <type_traits>
9
10#include "GaudiKernel/MsgStream.h"
11
12#include "AthenaBaseComps/AthMsgStreamMacros.h"
13#include "TrigNavigation/TypeMaps.h"
14#include "TrigNavStructure/BaseHolder.h"
15
16#ifndef TrigNavigation_Holder_icc
17#define TrigNavigation_Holder_icc
18
19#define HOLDERLOG(logger,x) if (logger->msgLvl(MSG::x)) logger->msg() << MSG::x
20
21/*
22template<class T>
23std::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);
28}
29*/
30
31/////////////////////////////////////////////////////////////////////////////
32// T is for objects, C for container for this objects
33template<class STORED>
34HLTNavDetails::Holder<STORED>::Holder() {
35}
36
37/////////////////////////////////////////////////////////////////////////////
38template<class STORED>
39HLTNavDetails::Holder<STORED>::Holder(const std::string& prefix, const std::string& label, uint16_t idx) :
40 IHolder(prefix, label, idx)
41{
42}
43
44
45/////////////////////////////////////////////////////////////////////////////
46namespace HLTNavDetails {
47template<class STORED>
48Holder<STORED>::~Holder() {
49}
50}
51
52/////////////////////////////////////////////////////////////////////////////
53template<class STORED, bool> struct createTemporary;
54
55/////////////////////////////////////////////////////////////////////////////
56template<class STORED>
57struct createTemporary<STORED, true>
58{
59 static STORED* do_it() {
60 STORED *s = new STORED;
61 s->clear(SG::VIEW_ELEMENTS);
62 return s;
63 }
64};
65
66/////////////////////////////////////////////////////////////////////////////
67template<class STORED>
68struct createTemporary<STORED, false>
69{
70 static STORED* do_it() {
71 return 0;
72 }
73};
74
75/////////////////////////////////////////////////////////////////////////////
76template<class STORED>
77template<class CONTAINER2>
78bool HLTNavDetails::Holder<STORED>::get( ElementLinkVector<CONTAINER2>& el, HLT::TriggerElement::ObjectIndex idx) {
79 return static_cast<HolderImp<STORED, CONTAINER2>* >(this)->getElementLinks(el, idx);
80}
81
82/////////////////////////////////////////////////////////////////////////////
83template<class STORED>
84template<class CONTAINER2>
85bool HLTNavDetails::Holder<STORED>::get( ElementLinkVector<CONTAINER2>& el ) {
86 return static_cast<HolderImp<STORED, CONTAINER2>* >(this)->getElementLinks(el);
87}
88
89
90/////////////////////////////////////////////////////////////////////////////
91// Implementation
92/////////////////////////////////////////////////////////////////////////////
93template<class STORED, class CONTAINER>
94HLTNavDetails::HolderImp<STORED, CONTAINER>::HolderImp()
95 : Holder<STORED>() {
96}
97
98/////////////////////////////////////////////////////////////////////////////
99template<class STORED, class CONTAINER>
100HLTNavDetails::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))
103{
104}
105
106/////////////////////////////////////////////////////////////////////////////
107namespace HLTNavDetails {
108template<class STORED, class CONTAINER>
109HolderImp<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.
113 m_memMgr.clear();
114}
115}
116
117
118/////////////////////////////////////////////////////////////////////////////
119template<class STORED, class CONTAINER>
120HLTNavDetails::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() ) {
123 return 0;
124 }
125 HolderImp<STORED, CONTAINER> *imp = new HolderImp<STORED, CONTAINER>(prefix, label, idx);
126 IHolder *h = imp;
127 return h;
128}
129
130template<class AUX>
131struct auxCLIDOrZero {
132 static CLID get() {
133 return ClassID_traits<AUX>::ID();
134 }
135 static std::string getName() {
136 return ClassID_traits<AUX>::typeName();
137 }
138};
139template<>
140struct auxCLIDOrZero<HLT::TypeInformation::no_aux> {
141 static CLID get() {
142 return 0;
143 }
144 static std::string getName() {
145 return std::string("no_aux");
146 }
147};
148
149/////////////////////////////////////////////////////////////////////////////
150template<class STORED, class CONTAINER>
151CLID HLTNavDetails::HolderImp<STORED, CONTAINER>::auxClidOrZero() const {
152 return auxCLIDOrZero<typename Container2Aux<CONTAINER>::type>::get();
153}
154
155/////////////////////////////////////////////////////////////////////////////
156template<class STORED, class CONTAINER>
157void 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();
161 if ( auxCLID ) {
162
163 if(H::m_readonly){
164 ATH_MSG_INFO("HolderImp::prepare using a read-only proxy for aux store");
165 H::m_aux = new TypelessAuxProxy();
166 }
167 else{
168
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);
172 return;
173 }
174
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);
178 }
179 ATH_MSG_VERBOSE("HolderImp::prepare proxy toAux store ready decorating");
180 }
181 }
182}
183
184
185/////////////////////////////////////////////////////////////////////////////
186template<class STORED, class CONTAINER>
187bool 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);
192 return false;
193 }
194 ATH_MSG_VERBOSE("HolderImp::syncWithSG syncing holder with SG " << *this);
195
196 const std::string auxkey = key()+"Aux.";
197 ATH_MSG_VERBOSE("HolderImp::syncWithSG looking in SG for key " << key() << " possible aux should have " << auxkey);
198
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);
205
206
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);
209 return false;
210 }
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);
213 return false;
214 };
215
216
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);
221 return false;
222 }
223
224 auto defaultPolicy = m_containerProxy.data()->ownPolicy();
225 m_containerProxy.data()->clear( defaultPolicy == SG::VIEW_ELEMENTS ? SG::VIEW_ELEMENTS : policy);
226
227
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);
232 return false;
233 }
234
235 ATH_MSG_VERBOSE("HolderImp::syncWithSG proxy toAux store ready decorating");
236
237 if( H::m_aux->create().isFailure() ) {
238 ATH_MSG_WARNING("HolderImp::syncWithSG can not create Aux store for container " << *this);
239 return false;
240 }
241
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);
244 return false;
245 }
246
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);
252 } else {
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);
255 return false;
256 }
257 }
258
259 if ( m_containerProxy.reg( H::m_storeGate, key()).isFailure() ) {
260 ATH_MSG_ERROR("HolderImp::syncWithSG recording collection failed " << *this);
261 return false;
262 }
263 }
264
265 return true;
266}
267
268/////////////////////////////////////////////////////////////////////////////
269template<class STORED, class CONTAINER>
270bool HLTNavDetails::HolderImp<STORED, CONTAINER>::checkAndSetOwnership(SG::OwnershipPolicy policy) {
271 if ( m_containerProxy.empty() )
272 return false;
273
274 if ( m_containerProxy.data()->empty() ) {
275 m_containerProxy.data()->clear(policy);
276 return true;
277 }
278
279 if ( m_containerProxy.data()->ownPolicy() == policy )
280 return true;
281
282 return false;
283}
284/////////////////////////////////////////////////////////////////////////////
285template<class CONTAINER, bool b>
286struct transferBetweenContainers;
287
288
289// case when the containers can be transfered
290template <class CONTAINER>
291struct transferBetweenContainers<CONTAINER, true> {
292 static void do_it(CONTAINER *source, CONTAINER* dest, const asg::AsgMessaging*) {
293 dest->insertMove (dest->end(), *source);
294 }
295};
296
297/////////////////////////////////////////////////////////////////////////////
298// case when the containers CAN NOT be transfered
299template <class CONTAINER>
300struct 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.");
306 }
307};
308
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)
312//
313template<class CONTAINER>
314struct canTransfer {
315 const static bool value = std::is_assignable<typename CONTAINER::iterator::reference,
316 typename CONTAINER::iterator::value_type>::value;
317};
318
319/////////////////////////////////////////////////////////////////////////////
320template<class STORED, class CONTAINER, bool b> struct insert;
321
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
328//
329template <class STORED, class CONTAINER>
330struct insert<STORED, CONTAINER, true>{
331 static bool do_it(STORED *source, CONTAINER* dest, bool /*hasAux*/, const asg::AsgMessaging* log) {
332
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;
336
337 // From Scott
338 // - Input container is owning. Output container should also be owning;
339 // ownership should be transferred from input to output container.
340
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.
344
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.)
349
350
351 if ( dest->empty() ) { // empty destination, we can do adaptations
352 if ( source->ownPolicy() == SG::OWN_ELEMENTS ) {
353 dest->clear( SG::OWN_ELEMENTS );
354 }
355
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);
360 }
361
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 );
366 }
367 }
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;
375 return false;
376 }
377
378
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;
382 } else {
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);
390 }
391 return true;
392 }
393};
394
395
396
397/////////////////////////////////////////////////////////////////////////////
398// implementation if stored and container are distinct
399template <class STORED, class CONTAINER>
400struct insert <STORED, CONTAINER, false>{
401 static bool do_it(STORED *s, CONTAINER* dest, bool /*hasAux*/, const asg::AsgMessaging*) {
402 dest->push_back(s);
403 return true;
404 }
405};
406
407/////////////////////////////////////////////////////////////////////////////
408template<class STORED, class CONTAINER, bool b> struct remap;
409template<class STORED, class CONTAINER>
410struct remap<STORED, CONTAINER, false> {
411 static void do_it(const std::string&, const std::string&, STORED *, CONTAINER*, HLT::AccessProxy*, const asg::AsgMessaging*) {
412
413 }
414};
415
416/////////////////////////////////////////////////////////////////////////////
417template<class STORED, class CONTAINER>
418struct 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 == "" ) {
422 // we can't do it
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);
425 if ( !px ) {
426 HOLDERLOG(log, WARNING) << "HolderImp::remap When remaping containers found no proxy for the object" << s << " of type " << ClassID_traits<STORED>::typeName() << endmsg;
427 return;
428 }
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;
431 return;
432 }
433 skey = px->name();
434 }
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());
438 }
439};
440
441template<class STORED, class CONTAINER, bool>
442struct destinationOwnPolicy {};
443
444template<class STORED, class CONTAINER>
445struct destinationOwnPolicy<STORED, CONTAINER, false> {
446 static SG::OwnershipPolicy get(const STORED* /*source*/) {
447 return SG::OWN_ELEMENTS;
448 }
449};
450
451template<class STORED, class CONTAINER>
452struct 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;
457 }
458};
459
460
461
462/////////////////////////////////////////////////////////////////////////////
463template<class STORED, class CONTAINER>
464HLT::TriggerElement::ObjectIndex HLTNavDetails::HolderImp<STORED, CONTAINER>::add ATLAS_NOT_THREAD_SAFE ( const STORED* f_in, bool inSG, const std::string& sgKey ) {
465 // FIXME:
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;
471
472 if ( ! syncWithSG( destinationOwnPolicy<STORED, CONTAINER, std::is_same<STORED, CONTAINER>::value>::get(f) ) )
473 return HLT::TriggerElement::ObjectIndex();
474
475 uint32_t bidx = m_containerProxy.data()->size();
476
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");
483 } else {
484 inSG = true;
485 wasRecorded = true;
486 ATH_MSG_VERBOSE("HolderImp::add feature SG direct registration succesful with the key:" << thiskey);
487 }
488 }
489
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);
493 }
494
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();
500 }
501
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 );
505
506 m_memMgr.insert(std::make_pair(objIdx, MemoryMgr(f, inSG||m_containerProxy.data()->ownPolicy() == SG::OWN_ELEMENTS)));
507
508 if ( wasRecorded ) {
509 if ( H::m_storeGate->setConst(f).isFailure() ) {
510 ATH_MSG_WARNING("HolderImp::add setConst failed " );
511 }
512 }
513
514 return objIdx;
515}
516
517
518/////////////////////////////////////////////////////////////////////////////
519template<class STORED, class CONTAINER, bool b> struct retrieve;
520
521/////////////////////////////////////////////////////////////////////////////
522// implementation if stored and container are the same
523template <class STORED, class CONTAINER>
524struct retrieve<STORED, CONTAINER, true>{
525 static bool do_it(const STORED*& dest, CONTAINER* src, HLT::TriggerElement::ObjectIndex idx) {
526 // find 2 iterators
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();
530 dest = 0;
531 return false;
532 }
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());
538
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);
544 return true;
545 }
546};
547
548/////////////////////////////////////////////////////////////////////////////
549// implementation if stored and container are distinct
550template <class STORED, class CONTAINER>
551struct retrieve <STORED, CONTAINER, false>{
552 static bool do_it(const STORED*& dest, CONTAINER* src, HLT::TriggerElement::ObjectIndex idx) {
553
554 if (idx.objectsBegin() < (*src).size()) {
555 dest = src->at(idx.objectsBegin());
556 return true;
557 } else {
558 dest = 0;
559 return false;
560 }
561 }
562};
563
564template<class STORED, class CONTAINER>
565bool HLTNavDetails::HolderImp<STORED, CONTAINER>::getWithLink(typename set_link<STORED,CONTAINER,std::is_same<STORED,CONTAINER>::value>::type& link,
566 HLT::TriggerElement::ObjectIndex& idx) {
567
568 const STORED* dest = 0;
569 bool result = this->get(dest,idx);
570 if(!result) return false;
571
572 link = set_link<STORED,CONTAINER,std::is_same<STORED,CONTAINER>::value>::do_it(dest,m_containerProxy.data(),idx);
573 return true;
574}
575
576/////////////////////////////////////////////////////////////////////////////
577template<class STORED, class CONTAINER>
578bool HLTNavDetails::HolderImp<STORED, CONTAINER>::get(const STORED*& dest, HLT::TriggerElement::ObjectIndex idx) {
579 typedef Holder<STORED> H;
580 if ( !syncWithSG() )
581 return false;
582
583
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();
589 return true;
590 }
591 else{
592 ATH_MSG_VERBOSE("HolderImp::get getting object from primary collection " << idx);
593 }
594
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);
600 return false;
601 }
602
603 if ( std::is_same<STORED, CONTAINER>::value ) { // temporary view containers in SG and cache filling
604
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 );
609
610 m_memMgr.insert(std::make_pair(idx, MemoryMgr(tempProxy, true))); // store it in the cache for futher uses
611
612 std::string sgKey = this->generateAliasKey(this->typeClid(), this->subTypeIndex(), this->label(), 0xffffffff );
613
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);
616 return false;
617 }
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);
621 }
622 return true;
623}
624
625
626/////////////////////////////////////////////////////////////////////////////
627// check if objects in obj are in the container
628template<class STORED, class CONTAINER, bool b> struct isin;
629
630/////////////////////////////////////////////////////////////////////////////
631// check if the container obj is a subcontainer of cont
632template <class STORED, class CONTAINER>
633struct 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() ) {
637 return false;
638 }
639 begin = it - cont->begin();
640 end = begin + obj->size();
641 return true;
642 }
643};
644
645/////////////////////////////////////////////////////////////////////////////
646// check if the obj is in a container cont
647template <class STORED, class CONTAINER>
648struct 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() ) {
652 return false;
653 }
654 begin = it - cont->begin();
655 end = begin+1;
656
657 return true;
658 }
659};
660
661template<class STORED, class CONTAINER>
662bool HLTNavDetails::HolderImp<STORED, CONTAINER>::contains(const STORED* obj, HLT::TriggerElement::ObjectIndex& idx) {
663 typedef Holder<STORED> H;
664 if ( !syncWithSG() )
665 return false;
666
667 ATH_MSG_VERBOSE("HolderImp::contains");
668 uint32_t begin=0;
669 uint32_t end=0;
670 bool ok = isin<STORED, CONTAINER,
671 std::is_same<STORED, CONTAINER>::value>::do_it (obj, m_containerProxy.data(), H::m_logger, begin, end);
672 if ( !ok ) {
673 ATH_MSG_VERBOSE("HolderImp::contains object " << obj << " not in the holder" << *this );
674 return false;
675 }
676 idx = HLT::TriggerElement::ObjectIndex(H::subTypeIndex(),begin,end);
677 ATH_MSG_VERBOSE("HolderImp::contains object " << obj << " found by in holder" << *this << " " << idx);
678 return true;
679}
680
681/////////////////////////////////////////////////////////////////////////////
682template<class STORED, class CONTAINER>
683bool HLTNavDetails::HolderImp<STORED, CONTAINER>::getElementLinks(ElementLinkVector<CONTAINER>& cont,
684 HLT::TriggerElement::ObjectIndex idx) {
685 //typedef Holder<STORED> H;
686 if ( !syncWithSG() )
687 return false;
688
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));
692 }
693 return true;
694}
695
696/////////////////////////////////////////////////////////////////////////////
697template<class STORED, class CONTAINER>
698bool HLTNavDetails::HolderImp<STORED, CONTAINER>::getElementLinks(ElementLinkVector<CONTAINER>& cont) {
699
700 //typedef Holder<STORED> H;
701 if ( !syncWithSG() )
702 return false;
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));
706 }
707 return true;
708}
709
710/////////////////////////////////////////////////////////////////////////////
711template<class STORED, class CONTAINER>
712std::string HLTNavDetails::HolderImp<STORED, CONTAINER>::getUniqueKey() {
713 ATH_MSG_VERBOSE("HolderImp::getUniqueKey");
714 if ( !syncWithSG() )
715 return "Bad_Key";
716 return IHolder::generateAliasKey( this->typeClid(), this->subTypeIndex(), this->label(),
717 m_containerProxy.data()->size() );
718}
719
720template<class STORED, class CONTAINER>
721std::string HLTNavDetails::HolderImp<STORED, CONTAINER>::getNextKey() {
722 ATH_MSG_VERBOSE("HolderImp::getNextKey");
723 return getUniqueKey();
724}
725
726
727
728
729/////////////////////////////////////////////////////////////////////////////
730template<class STORED, class CONTAINER>
731bool HLTNavDetails::HolderImp<STORED, CONTAINER>::serialize(std::vector<uint32_t>& output) const {
732 typedef Holder<STORED> H; // this is to make things below shorter
733
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);
737
738 return true;
739}
740
741/////////////////////////////////////////////////////////////////////////////
742template<class STORED, class CONTAINER>
743void HLTNavDetails::HolderImp<STORED, CONTAINER>::print(MsgStream& m) const {
744 IHolder::print(m);
745 if ( not m_containerProxy.empty() )
746 m << " size: " << m_containerProxy.data()->size() << " @"<<m_containerProxy.data();
747 else
748 m << " container not allocated yet";
749}
750
751/////////////////////////////////////////////////////////////////////////////
752template<class STORED, class CONTAINER>
753DataObject* HLTNavDetails::HolderImp<STORED, CONTAINER>::getDataObject() {
754 if(!m_containerProxy.data()) return 0;
755 return SG::asStorable(m_containerProxy.data());
756}
757
758#define _IS_AUXTYPE_ !std::is_same<typename Container2Aux<T>::type,HLT::TypeInformation::no_aux>::value
759
760struct AuxDataObjectHelper{
761 template<typename T>
762 static typename std::enable_if<!_IS_AUXTYPE_,DataObject*>::type get(HLTNavDetails::ITypeProxy*/* aux*/){
763 return 0;
764 }
765 template<typename T>
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);
769 if(auxcasted){
770 if(!auxcasted->data()) return 0;
771 return SG::asStorable(auxcasted->data());
772 }
773 return 0;
774 }
775 template<typename T>
776 static typename std::enable_if<!_IS_AUXTYPE_,bool>::type set(HLTNavDetails::ITypeProxy*,DataObject*){
777 return true;//always success
778 }
779 template<typename T>
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);
783 if(auxcasted){
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;
787 return success;
788 }
789 return 0;
790 }
791};
792
793template<class STORED, class CONTAINER>
794DataObject* HLTNavDetails::HolderImp<STORED, CONTAINER>::getAuxDataObject() {
795 return AuxDataObjectHelper::get<CONTAINER>(this->m_aux);
796}
797
798template<class STORED, class CONTAINER>
799bool 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);
807 return false;
808 }
809 SG::IAuxStore* aux = this->m_aux->castIAuxStore();
810 if(!aux){
811 ATH_MSG_ERROR("cast of auxstore failed");
812 }
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);
817 return true;
818 }
819 ATH_MSG_WARNING("something went wrong setting aux data object");
820 return false;
821}
822
823
824/////////////////////////////////////////////////////////////////////////////
825template<class STORED, class CONTAINER>
826bool 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();
830 return success;
831}
832
833/////////////////////////////////////////////////////////////////////////////
834template<class STORED, class CONTAINER>
835HLTNavDetails::HolderImp<STORED, CONTAINER>::MemoryMgr::MemoryMgr(const FeatureProxy& st, bool sg)
836 : proxy(st), inSG(sg)
837{}
838
839/////////////////////////////////////////////////////////////////////////////
840template<class STORED, class CONTAINER>
841HLTNavDetails::HolderImp<STORED, CONTAINER>::MemoryMgr::MemoryMgr()
842 : inSG(false)
843{}
844
845/////////////////////////////////////////////////////////////////////////////
846template<class STORED, class CONTAINER>
847void 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();
849}
850
851/////////////////////////////////////////////////////////////////////////////
852template<class STORED>
853MsgStream& HLTNavDetails::operator<< ( MsgStream& m, const HLTNavDetails::Holder<STORED>& h ) {
854 h.print(m);
855 return m;
856}
857
858/////////////////////////////////////////////////////////////////////////////
859template<class STORED, class CONTAINER>
860MsgStream& HLTNavDetails::operator<< ( MsgStream& m, const HLTNavDetails::HolderImp<STORED, CONTAINER>& h ) {
861 h.print(m);
862 return m;
863}
864
865#endif