ATLAS Offline Software
Loading...
Searching...
No Matches
AnaToolHandle.icc
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
5#ifndef ASGTOOLS_ANATOOLHANDLE_ICC
6#define ASGTOOLS_ANATOOLHANDLE_ICC
7
8#include <AsgTools/MessageCheckAsgTools.h>
9#include "CxxUtils/checker_macros.h"
10#include <assert.h>
11#include <cstdlib>
12
13#ifndef XAOD_STANDALONE
14#include "Gaudi/Interfaces/IOptionsSvc.h"
15#endif
16
17
18namespace asg
19{
20 namespace detail
21 {
22#ifdef XAOD_STANDALONE
23 StatusCode makeToolRootCore (const std::string& type,
24 const std::string& name,
25 AsgTool*& tool);
26#else
27 StatusCode readToolConfig (AsgToolConfig& config, const std::string& toolName);
28 StatusCode copyPropertiesInCatalogue( const std::string& fromTool, const std::string& toTool );
29 StatusCode hasPropertiesInCatalogue( const std::string& toolName );
30 StatusCode addPropertyToCatalogue( const std::string& toolName, const std::string& property, const std::string& val);
31 StatusCode removePropertyFromCatalogue( const std::string& toolName, const std::string& property);
32 StatusCode toolExists( const std::string& fullName, interfaceType_t*& tool );
33#endif
34
35
36
37 /// \brief do a checked cast from one ToolHandle interface to
38 /// another
39 /// \par Guarantee
40 /// basic
41 /// \par Failures
42 /// interface not supported for tool
43 template<typename T1,typename T2> StatusCode
44 toolHandleCast (ToolHandle<T1>& to, ToolHandle<T2>& from)
45 {
46 using namespace msgUserCode;
47
48#ifdef XAOD_STANDALONE
49 to = ToolHandle<T1> (dynamic_cast<T1*>(&*from));
50 if (!from.empty() && to.operator->() == nullptr)
51 {
52 ANA_MSG_ERROR ("failed to cast from type " << typeid(T2).name() << " to " << typeid(T1).name());
53 return StatusCode::FAILURE;
54 }
55#else
56 to = ToolHandle<T1> (from.typeAndName(), from.parent());
57 if (!from.empty())
58 ANA_CHECK (to.retrieve());
59#endif
60 return StatusCode::SUCCESS;
61 }
62
63
64
65
66
67 /// \brief the information needed to share a tool
68
69 class AnaToolShare
70 {
71 //
72 // public interface
73 //
74
75 /// \brief standard constructor
76 /// \par Guarantee
77 /// strong
78 /// \par Failures
79 /// out of memory II
80 public:
81 AnaToolShare (const ToolHandle<interfaceType_t>& val_th,
82 std::shared_ptr<void> val_cleanup,
83 std::vector<std::function<StatusCode ()>>&& extraInit);
84
85
86 /// \brief the tool we contain
87 /// \par Guarantee
88 /// no-fail
89 /// \post result != nullptr
90 public:
91 ToolHandle<interfaceType_t>& th ();
92
93
94
95 //
96 // private interface
97 //
98
99 /// \brief the value of \ref tool
100 private:
101 ToolHandle<interfaceType_t> m_th;
102
103 /// \brief resources to release when we are releasing the tool
104 private:
105 std::vector<std::function<StatusCode ()>> m_extraInit;
106
107 /// \brief resources to release when we are releasing the tool
108 private:
109 std::shared_ptr<void> m_cleanup;
110 };
111
112
113
114
115
116 /// \brief a service for sharing tools of a given type
117
118 class AnaToolShareList
119 {
120 //
121 // public interface
122 //
123
124 /// \brief the singleton we are using
125 /// \par Guarantee
126 /// no-fail
127 public:
128 static AnaToolShareList& singleton () noexcept;
129
130
131 /// \brief get the share for the given name, or nullptr if no
132 /// share has been defined
133 /// \par Guarantee
134 /// strong
135 /// \par Failures
136 /// out of memory I
137 public:
138 std::shared_ptr<AnaToolShare>
139 getShare (const std::string& name) const;
140
141
142 /// \brief set the share for the given name
143 /// \return the share to use, this is either the share passed in
144 /// or the already set share
145 /// \par Guarantee
146 /// strong
147 /// \par Failures
148 /// out of memory II
149 private:
150 std::shared_ptr<AnaToolShare>
151 setShare (const std::string& name,
152 std::unique_ptr<AnaToolShare> val_share);
153
154
155 /// \brief make or get a share for the given name
156 /// \return the share to use, either freshly created or
157 /// retrieved from the store
158 /// \par Guarantee
159 /// strong
160 /// \par Failures
161 /// tool creation failures\n
162 /// out of memory II
163 public:
164 StatusCode
165 makeShare (const std::string& name,
166 const AsgToolConfig& config,
167 std::vector<std::function<StatusCode ()>>&& extraInit,
168 std::shared_ptr<AnaToolShare>& result);
169
170
171
172 //
173 // private interface
174 //
175
176 /// \brief the shares we manage
177 private:
178 std::map<std::string,std::weak_ptr<AnaToolShare> > m_shared;
179 mutable std::recursive_mutex m_mutex;
180 typedef std::lock_guard<std::recursive_mutex> lock_t;
181 };
182 }
183
184
185
186 template <typename T>
187 std::ostream& operator << (std::ostream& str, const AnaToolHandle<T>& obj)
188 {
189 return str << obj.getHandle();
190 }
191
192
193
194 template<class T> void AnaToolHandle<T> ::
195 testInvariant () const
196 {
197#define CHECK_INVARIANT(x) \
198 if (!(x)) { std::cerr << __FILE__ << ":" << __LINE__ << ": invariant violated: " << #x << std::endl; std::abort(); }
199
200 // General requirements
201 CHECK_INVARIANT (m_handleUser != nullptr);
202 CHECK_INVARIANT (m_name == m_config.name());
203
204#undef CHECK_INVARIANT
205 }
206
207
208
209 template<class T> AnaToolHandle<T> ::
210 AnaToolHandle (const std::string& val_name, parentType_t *val_parent)
211 : m_parentPtr (val_parent),
212 m_handleUser (new ToolHandle<T> (val_name, val_parent)),
213 m_allowEmpty (val_name.empty())
214 {
215 setTypeAndName (val_name);
216
217#ifndef NDEBUG
218 this->testInvariant ();
219#endif
220 }
221
222
223
224 template<class T> AnaToolHandle<T> ::
225 AnaToolHandle (AnaToolHandle<T>&& that)
226 : AnaToolHandle ()
227 {
228 swap (that);
229 }
230
231
232
233 template<class T> AnaToolHandle<T> ::
234 AnaToolHandle (const AnaToolHandle<T>& that)
235 : m_config (that.m_config),
236 m_name (that.m_name),
237 m_parentPtr (that.m_parentPtr),
238 m_handleUser (new ToolHandle<T> (*that.m_handleUser)),
239 m_originalTypeAndName (that.m_originalTypeAndName),
240 m_isInitialized (that.m_isInitialized.load()),
241 m_allowEmpty (that.m_allowEmpty)
242 {
243 if (m_isInitialized.load())
244 {
245 m_toolPtr = that.m_toolPtr.load();
246 m_mode = that.m_mode;
247 m_extraInit = that.m_extraInit;
248 m_cleanup = that.m_cleanup;
249 }
250
251#ifndef XAOD_STANDALONE
252 if (!m_handleUser->empty())
253 (*m_handleUser)->release();
254#endif
255
256#ifndef NDEBUG
257 that.testInvariant ();
258 testInvariant ();
259#endif
260 }
261
262
263
264 template<class T> AnaToolHandle<T>& AnaToolHandle<T> ::
265 operator = (const AnaToolHandle<T>& that)
266 {
267 // no invariant used
268 AnaToolHandle<T> (that).swap (*this);
269 return *this;
270 }
271
272
273
274 template<class T> void AnaToolHandle<T> ::
275 swap (AnaToolHandle<T>& that) noexcept
276 {
277#ifndef NDEBUG
278 testInvariant ();
279 that.testInvariant ();
280#endif
281
282 std::swap (m_extraInit, that.m_extraInit);
283 std::swap (m_cleanup, that.m_cleanup);
284 std::swap (m_config, that.m_config);
285 m_name.swap (that.m_name);
286 std::swap (m_parentPtr, that.m_parentPtr);
287 {
288 ToolHandle<T> tmp = *m_handleUser;
289#ifndef XAOD_STANDALONE
290 if (!tmp.empty()) {
291 try {
292 tmp->release();
293 }
294 catch (const GaudiException&) {
295 std::abort();
296 }
297 }
298#endif
299 *m_handleUser = *that.m_handleUser;
300 *that.m_handleUser = std::move(tmp);
301 }
302 m_originalTypeAndName.swap (that.m_originalTypeAndName);
303 {
304 const auto tmp = m_isInitialized.load();
305 m_isInitialized = that.m_isInitialized.load();
306 that.m_isInitialized = tmp;
307 }
308 {
309 const auto tmp = m_toolPtr.load();
310 m_toolPtr = that.m_toolPtr.load();
311 that.m_toolPtr = tmp;
312 }
313 std::swap (m_mode, that.m_mode);
314 std::swap (m_allowEmpty, that.m_allowEmpty);
315
316#ifndef NDEBUG
317 testInvariant ();
318 that.testInvariant ();
319#endif
320 }
321
322
323
324 template<class T> AnaToolHandle<T>& AnaToolHandle<T> ::
325 operator = (AnaToolHandle<T>&& that)
326 {
327 // no invariant used
328 swap (that);
329 return *this;
330 }
331
332
333
334 template<class T> AnaToolHandle<T> ::
335 ~AnaToolHandle () noexcept
336 {
337 using namespace msgToolHandle;
338#ifndef NDEBUG
339 this->testInvariant ();
340#endif
341 }
342
343
344 template<class T> bool
345 AnaToolHandle<T> ::
346 empty () const
347 {
348#ifndef NDEBUG
349 this->testInvariant ();
350#endif
351 switch (getMode())
352 {
353 case detail::AnaToolHandleMode::EMPTY:
354 return true;
355 case detail::AnaToolHandleMode::CREATE_PRIVATE:
356 case detail::AnaToolHandleMode::CREATE_SHARED:
357 case detail::AnaToolHandleMode::RETRIEVE_SHARED:
358 return false;
359 case detail::AnaToolHandleMode::USER:
360 return m_handleUser->empty();
361 }
362 return false; //compiler dummy
363 }
364
365
366
367 template<class T> inline bool AnaToolHandle<T> ::
368 isPublic () const noexcept
369 {
370#ifndef NDEBUG
371 this->testInvariant ();
372#endif
373 return m_parentPtr == nullptr;
374 }
375
376
377
378 template<class T> inline const std::string& AnaToolHandle<T> ::
379 type () const noexcept
380 {
381#ifndef NDEBUG
382 this->testInvariant ();
383#endif
384 return m_config.type();
385 }
386
387
388
389 template<class T> inline const std::string&
390 AnaToolHandle<T> ::
391 name () const noexcept
392 {
393#ifndef NDEBUG
394 this->testInvariant ();
395#endif
396 return m_name;
397 }
398
399
400
401 template<typename T> template<typename T2>
402 StatusCode AnaToolHandle<T> ::
403 setProperty (const std::string& property, const T2& value)
404 {
405 using namespace msgToolHandle;
406
407#ifndef NDEBUG
408 this->testInvariant ();
409 if (isInitialized())
410 {
411 ANA_MSG_FATAL ("AnaToolHandle has already been initialized: " << *this);
412 std::abort();
413 }
414#endif
415
416 return m_config.setProperty (property, value);
417 }
418
419
420
421 template<typename T> template<typename T2>
422 typename std::enable_if<std::is_base_of_v<parentType_t, T2>, StatusCode>::type
423 AnaToolHandle<T> ::
424 setProperty (const std::string& property,
425 const ToolHandle<T2>& value)
426 {
427 using namespace msgToolHandle;
428
429#ifndef NDEBUG
430 this->testInvariant ();
431 if (isInitialized())
432 {
433 ANA_MSG_FATAL ("AnaToolHandle has already been initialized: " << *this);
434 std::abort();
435 }
436#endif
437
438 ANA_MSG_DEBUG ("adding sub-tool from ToolHandle: " << value);
439 if (value.empty())
440 return setProperty (property, std::string ());
441#ifndef XAOD_STANDALONE
442 else if (value.isPublic())
443#else
444 else if (value.parentName() == "ToolSvc")
445#endif
446 {
447 return setProperty (property,
448 value.type() + "/" + value.name());
449 } else
450 {
451#ifndef XAOD_STANDALONE
452 AsgToolConfig subToolConfig;
453 ANA_CHECK (detail::readToolConfig (subToolConfig, value.parentName() + "." + value.name()));
454 ANA_CHECK (m_config.addPrivateTool (property, std::move(subToolConfig)));
455 return StatusCode::SUCCESS;
456#else
457 return setProperty (property, value.name());
458#endif
459 }
460 }
461
462
463
464 template<typename T> template<typename T2>
465 StatusCode AnaToolHandle<T> ::
466 setProperty (const std::string& property,
467 const AnaToolHandle<T2>& value)
468 {
469 using namespace msgToolHandle;
470
471#ifndef NDEBUG
472 this->testInvariant ();
473 if (isInitialized())
474 {
475 ANA_MSG_FATAL ("AnaToolHandle has already been initialized: " << *this);
476 std::abort();
477 }
478#endif
479
480 // once initialized the AnaToolHandle is not that different from
481 // a regular ToolHandle and we just use it as such
482 if (value.isInitialized())
483 return setProperty (property, value.getHandle());
484
485 ANA_MSG_DEBUG ("adding sub-tool from AnaToolHandle with mode " << unsigned (value.mode()) << " and name " << value.name());
486 switch (value.mode())
487 {
488 case detail::AnaToolHandleMode::EMPTY:
489 return setProperty (property, ToolHandle<T2> ());
490 case detail::AnaToolHandleMode::CREATE_PRIVATE:
491 return m_config.addPrivateTool (property, value.config());
492 case detail::AnaToolHandleMode::CREATE_SHARED:
493 case detail::AnaToolHandleMode::RETRIEVE_SHARED:
494 m_extraInit.emplace_back ([toolhandle = value] () mutable -> StatusCode
495 {
496 ANA_CHECK (toolhandle.initialize());
497 return StatusCode::SUCCESS;
498 });
499 return m_config.setProperty (property, value.name());
500 case detail::AnaToolHandleMode::USER:
501 return setProperty (property, value.getHandle());
502 }
503 return StatusCode::FAILURE; //compiler dummy
504 }
505
506
507
508 template<typename T> template<typename T2>
509 typename std::enable_if<std::is_base_of_v<parentType_t, T2>, StatusCode>::type
510 AnaToolHandle<T> ::
511 setProperty (const std::string& property,
512 const ToolHandleArray<T2>& value)
513 {
514 using namespace msgToolHandle;
515
516#ifndef NDEBUG
517 this->testInvariant ();
518 if (isInitialized())
519 {
520 ANA_MSG_FATAL ("AnaToolHandle has already been initialized: " << *this);
521 std::abort();
522 }
523#endif
524
525 std::vector<std::string> tools;
526 // loop over toolhandles in array, strip off any parent naming
527 // and set property with the result
528 for (auto& toolHandle : value)
529 {
530 if (toolHandle.empty())
531 {
532 ANA_MSG_ERROR ("trying to initialize ToolHandleArray property " << property << " with empty handle");
533 return StatusCode::FAILURE;
534 }
535
536 tools.push_back (toolHandle.type() + "/" + toolHandle.name());
537 }
538
539 return setProperty (property, tools);
540 }
541
542
543
544 template<class T> StatusCode
545 AnaToolHandle<T> ::
546 initialize ()
547 {
548 using namespace msgToolHandle;
549
550 // ensure we don't initialize twice concurrently
551 std::lock_guard<std::recursive_mutex> lock (m_initializeMutex);
552
553#ifndef NDEBUG
554 this->testInvariant ();
555 if (isInitialized())
556 {
557 ANA_MSG_FATAL ("AnaToolHandle has already been initialized: " << *this);
558 std::abort();
559 }
560#endif
561
562 std::shared_ptr<detail::AnaToolShare> sharedTool;
563 const detail::AnaToolHandleMode mode = getMode (sharedTool);
564
565 ToolHandle<T> th (typeAndName(), m_parentPtr);
566 std::shared_ptr<void> cleanup;
567
568 switch (mode)
569 {
570 case detail::AnaToolHandleMode::EMPTY:
571 break;
572 case detail::AnaToolHandleMode::CREATE_PRIVATE:
573 for (auto& extraInit : m_extraInit)
574 ANA_CHECK (extraInit());
575 ANA_CHECK (m_config.makeTool (th, cleanup, true));
576 break;
577 case detail::AnaToolHandleMode::CREATE_SHARED:
578 ANA_CHECK (detail::AnaToolShareList::singleton().makeShare (m_name, m_config, std::move (m_extraInit), sharedTool));
579 // FALLTHROUGH
580 case detail::AnaToolHandleMode::RETRIEVE_SHARED:
581 assert (sharedTool != nullptr);
582 ANA_CHECK (detail::toolHandleCast (th, sharedTool->th()));
583#ifndef XAOD_STANDALONE
584 if (!th.empty())
585 th->release ();
586#endif
587 cleanup = sharedTool;
588 break;
589 case detail::AnaToolHandleMode::USER:
590 th = *m_handleUser;
591 if (th.empty() && !m_allowEmpty)
592 {
593 ANA_MSG_ERROR ("user configured an empty handle for a non-empty AnaToolHandle: " << *this);
594 return StatusCode::FAILURE;
595 }
596 break;
597 }
598
599 T *toolPtr = nullptr;
600 ANA_CHECK (makeToolRetrieve (toolPtr, th));
601
602 *m_handleUser = th;
603#ifndef XAOD_STANDALONE
604 if (!th.empty())
605 th->release ();
606#endif
607 m_mode = mode;
608 std::swap (m_cleanup, cleanup);
609 m_toolPtr = toolPtr;
610 m_isInitialized = true;
611
612#ifndef NDEBUG
613 this->testInvariant ();
614#endif
615 return StatusCode::SUCCESS;
616 }
617
618
619
620 template<class T> StatusCode
621 AnaToolHandle<T> ::
622 retrieve ()
623 {
624 // no invariant used
625 return initialize ();
626 }
627
628
629 template<class T> bool
630 AnaToolHandle<T> ::
631 isConfigurable () const
632 {
633 using namespace msgToolHandle;
634#ifndef NDEBUG
635 this->testInvariant ();
636#endif
637 switch (getMode())
638 {
639 case detail::AnaToolHandleMode::EMPTY:
640 case detail::AnaToolHandleMode::CREATE_PRIVATE:
641 case detail::AnaToolHandleMode::CREATE_SHARED:
642 return true;
643 case detail::AnaToolHandleMode::RETRIEVE_SHARED:
644 case detail::AnaToolHandleMode::USER:
645 return false;
646 }
647 return true; //compiler dummy
648 }
649
650
651
652 template<class T>
653#ifndef NDEBUG
654 inline
655#endif
656 bool AnaToolHandle<T> ::
657 isInitialized () const noexcept
658 {
659#ifndef NDEBUG
660 this->testInvariant ();
661#endif
662 return m_isInitialized;
663 }
664
665
666
667 template<class T> inline T *
668 AnaToolHandle<T> ::
669 operator -> ()
670 {
671 // no invariant used
672 return get ();
673 }
674
675
676
677 template<class T> inline const T *
678 AnaToolHandle<T> ::
679 operator -> () const
680 {
681 // no invariant used
682 return get ();
683 }
684
685
686
687 template<class T> inline T&
688 AnaToolHandle<T> ::
689 operator * ()
690 {
691 // no invariant used
692 return *get ();
693 }
694
695
696
697 template<class T> inline const T&
698 AnaToolHandle<T> ::
699 operator * () const
700 {
701 // no invariant used
702 return *get ();
703 }
704
705
706
707 template<class T> inline T*
708 AnaToolHandle<T> ::
709 get ()
710 {
711 using namespace msgToolHandle;
712
713#ifndef NDEBUG
714 this->testInvariant ();
715#endif
716
717 if (m_isInitialized.load())
718 return m_toolPtr;
719
720 {
721 std::lock_guard<std::recursive_mutex> lock (m_initializeMutex);
722 if (!m_isInitialized)
723 ANA_CHECK_THROW (initialize());
724 assert (m_isInitialized);
725 }
726 return m_toolPtr;
727 }
728
729
730
731 template<class T> inline const T*
732 AnaToolHandle<T> ::
733 get () const
734 {
735 AnaToolHandle<T>* this_nc ATLAS_THREAD_SAFE = const_cast<AnaToolHandle<T>*>(this);
736 return this_nc->get();
737 }
738
739
740
741 template <class T> template<typename T2> void
742 AnaToolHandle<T> ::
743 declarePropertyFor (T2 *tool, const std::string& name,
744 const std::string& description)
745 {
746 using namespace msgToolHandle;
747#ifndef NDEBUG
748 this->testInvariant ();
749 if (isInitialized())
750 {
751 ANA_MSG_FATAL ("can't declare tool handle " << *this << " as property " << name << " after tool has been instantiated");
752 std::abort ();
753 }
754#endif
755
756 if (m_parentPtr != nullptr && m_parentPtr != tool)
757 {
758 ANA_MSG_FATAL ("can't declare tool handle " << *this << " as property for tool " << tool->name() << " as it has a different parent tool " << m_parentPtr->name());
759 std::abort ();
760 }
761 if (m_originalTypeAndName.empty())
762 m_originalTypeAndName = m_handleUser->typeAndName ();
763 ANA_CHECK_THROW (tool->declareProperty (name, *m_handleUser, description));
764 }
765
766
767
768
769
770
771 template <class T> const ToolHandle<T>&
772 AnaToolHandle<T> ::
773 getHandle () const noexcept
774 {
775#ifndef NDEBUG
776 this->testInvariant ();
777#endif
778 return *m_handleUser;
779 }
780
781
782
783 template <class T> bool
784 AnaToolHandle<T> ::
785 isUserConfigured () const
786 {
787 using namespace msgToolHandle;
788#ifndef NDEBUG
789 this->testInvariant ();
790#endif
791
792 // getMode can throw an exception (from dereferencing the ToolSvc handle),
793 // so this function is not noexcept.
794 switch (getMode())
795 {
796 case detail::AnaToolHandleMode::EMPTY:
797 case detail::AnaToolHandleMode::CREATE_PRIVATE:
798 case detail::AnaToolHandleMode::CREATE_SHARED:
799 return false;
800 case detail::AnaToolHandleMode::RETRIEVE_SHARED:
801 case detail::AnaToolHandleMode::USER:
802 return true;
803 }
804 return false; //compiler dummy
805 }
806
807
808
809 template<class T> std::string
810 AnaToolHandle<T> ::
811 fullName () const
812 {
813#ifndef NDEBUG
814 this->testInvariant ();
815#endif
816#ifndef XAOD_STANDALONE
817 return m_handleUser->parentName() + "." + name();
818#else
819 std::string toolName;
820 if (m_parentPtr)
821 toolName = m_parentPtr->name() + "." + name();
822 else
823 toolName = "ToolSvc." + name();
824 return toolName;
825#endif
826 }
827
828
829
830 template<class T> detail::AnaToolHandleMode AnaToolHandle<T> ::
831 getMode (std::shared_ptr<detail::AnaToolShare>& sharedTool) const
832 {
833 using namespace msgToolHandle;
834#ifndef NDEBUG
835 this->testInvariant ();
836#endif
837
838 assert (!m_isInitialized);
839
840 if (m_handleUser->isSet())
841 return detail::AnaToolHandleMode::USER;
842
843 if (m_config.empty() && m_name.empty())
844 return detail::AnaToolHandleMode::EMPTY;
845
846 if (!m_originalTypeAndName.empty() &&
847 m_handleUser->typeAndName() != m_originalTypeAndName)
848 return detail::AnaToolHandleMode::USER;
849
850#ifdef XAOD_STANDALONE
851 if (m_parentPtr != nullptr)
852 {
853 if (m_handleUser->parentName() != m_parentPtr->name())
854 return detail::AnaToolHandleMode::USER;
855 } else
856 {
857 if (m_handleUser->parentName() != "ToolSvc")
858 return detail::AnaToolHandleMode::USER;
859 }
860#endif
861
862 if (isPublic())
863 {
864 if ((sharedTool = detail::AnaToolShareList::singleton()
865 .getShare (name())))
866 return detail::AnaToolHandleMode::RETRIEVE_SHARED;
867#ifdef XAOD_STANDALONE
868 /// \todo check whether this is actually what we want to do
869 if (ToolStore::contains<T> (m_handleUser->name()))
870 return detail::AnaToolHandleMode::USER;
871#endif
872 }
873
874#ifndef XAOD_STANDALONE
875 //for athena, all we do here is check if the tool already exists
876 interfaceType_t *tool = nullptr;
877 if( detail::toolExists( fullName(), tool ) )
878 return detail::AnaToolHandleMode::USER;
879
880 if (detail::hasPropertiesInCatalogue (fullName()))
881 return detail::AnaToolHandleMode::USER;
882#endif
883
884 if (m_config.empty() && !m_handleUser->typeAndName().empty() && (m_handleUser->type() != this->type() || m_handleUser->name() != this->name()))
885 return detail::AnaToolHandleMode::USER;
886
887 if (isPublic())
888 return detail::AnaToolHandleMode::CREATE_SHARED;
889 else
890 return detail::AnaToolHandleMode::CREATE_PRIVATE;
891 }
892
893
894
895 template<class T> detail::AnaToolHandleMode AnaToolHandle<T> ::
896 getMode () const
897 {
898 if (m_isInitialized)
899 return m_mode;
900
901 std::shared_ptr<detail::AnaToolShare> sharedTool;
902 return getMode (sharedTool);
903 }
904
905
906
907 template<class T> std::string AnaToolHandle<T> ::
908 typeAndName () const
909 {
910#ifndef NDEBUG
911 this->testInvariant ();
912#endif
913 return m_config.typeAndName();
914 }
915
916
917
918 template<class T> void AnaToolHandle<T> ::
919 setType (std::string val_type) noexcept
920 {
921 using namespace msgToolHandle;
922#ifndef NDEBUG
923 this->testInvariant ();
924 if (isInitialized())
925 {
926 ANA_MSG_FATAL ("AnaToolHandle has already been initialized: " << *this);
927 std::abort();
928 }
929#endif
930
931 m_config.setType (std::move (val_type));
932 if (m_originalTypeAndName.empty() &&
933 !this->type().empty() && !this->name().empty())
934 m_handleUser->setTypeAndName (this->type() + "/" + this->name());
935
936#ifndef NDEBUG
937 this->testInvariant ();
938#endif
939 }
940
941
942
943 template<class T> void AnaToolHandle<T> ::
944 setName (std::string val_name) noexcept
945 {
946 using namespace msgToolHandle;
947#ifndef NDEBUG
948 this->testInvariant ();
949 if (isInitialized())
950 {
951 ANA_MSG_FATAL ("AnaToolHandle has already been initialized: " << *this);
952 std::abort();
953 }
954#endif
955
956 m_config.setName (val_name);
957 m_name = std::move (val_name);
958 if (m_originalTypeAndName.empty() &&
959 !this->type().empty() && !this->name().empty())
960 m_handleUser->setTypeAndName (this->type() + "/" + this->name());
961
962#ifndef NDEBUG
963 this->testInvariant ();
964#endif
965 }
966
967
968
969 template<class T> void AnaToolHandle<T> ::
970 setTypeAndName (const std::string& val_typeAndName)
971 {
972 using namespace msgToolHandle;
973#ifndef NDEBUG
974 if (isInitialized())
975 {
976 ANA_MSG_FATAL ("AnaToolHandle has already been initialized: " << *this);
977 std::abort();
978 }
979#endif
980 auto split = val_typeAndName.find ("/");
981 if (split != std::string::npos)
982 {
983 setTypeAndName (val_typeAndName.substr (0, split),
984 val_typeAndName.substr (split+1));
985 } else
986 {
987 setTypeAndName (val_typeAndName, val_typeAndName);
988 }
989 }
990
991
992
993 template<class T> void AnaToolHandle<T> ::
994 setTypeAndName (std::string val_type, std::string val_name) noexcept
995 {
996 using namespace msgToolHandle;
997#ifndef NDEBUG
998 if (isInitialized())
999 {
1000 ANA_MSG_FATAL ("AnaToolHandle has already been initialized: " << *this);
1001 std::abort();
1002 }
1003#endif
1004 setType (std::move (val_type));
1005 setName (std::move (val_name));
1006 }
1007
1008
1009
1010 template<class T> StatusCode AnaToolHandle<T> ::
1011 makeToolRetrieve (T*& toolPtr, ToolHandle<T>& toolHandle) const
1012 {
1013 using namespace msgToolHandle;
1014
1015 if (toolHandle.empty())
1016 {
1017 toolPtr = nullptr;
1018 return StatusCode::SUCCESS;
1019 }
1020
1021 try
1022 {
1023 toolPtr = toolHandle.operator->();
1024 if (toolPtr == nullptr)
1025 {
1026 ANA_MSG_ERROR ("failed to retrieve tool from tool handle " << *m_handleUser);
1027 return StatusCode::FAILURE;
1028 }
1029 return StatusCode::SUCCESS;
1030 } catch (std::exception& e)
1031 {
1032 ANA_MSG_ERROR ("encountered exception during tool retrieval (" << toolHandle << "): " << e.what());
1033 return StatusCode::FAILURE;
1034 }
1035 }
1036
1037
1038
1039 template<class T> detail::AnaToolHandleMode AnaToolHandle<T> ::
1040 mode () const
1041 {
1042#ifndef NDEBUG
1043 this->testInvariant ();
1044#endif
1045 return getMode ();
1046 }
1047
1048
1049
1050 template<class T> const AsgToolConfig& AnaToolHandle<T> ::
1051 config () const
1052 {
1053#ifndef NDEBUG
1054 this->testInvariant ();
1055#endif
1056 return m_config;
1057 }
1058
1059
1060
1061 template<class T> bool AnaToolHandle<T> ::
1062 allowEmpty () const noexcept
1063 {
1064#ifndef NDEBUG
1065 this->testInvariant ();
1066#endif
1067 return m_allowEmpty;
1068 }
1069
1070
1071
1072 template<class T> void AnaToolHandle<T> ::
1073 setAllowEmpty (bool val_allowEmpty) noexcept
1074 {
1075 using namespace msgToolHandle;
1076#ifndef NDEBUG
1077 this->testInvariant ();
1078 if (isInitialized())
1079 {
1080 ANA_MSG_FATAL ("AnaToolHandle has already been initialized: " << *this);
1081 std::abort();
1082 }
1083#endif
1084 m_allowEmpty = val_allowEmpty;
1085 }
1086}
1087
1088#endif // ASGTOOLS_ANATOOLHANDLE_ICC