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 typename std::enable_if<std::is_base_of_v<parentType_t, T2>, StatusCode>::type
466 AnaToolHandle<T> ::
467 setProperty (const std::string& property,
468 const PublicToolHandle<T2>& value)
469 {
470 // without this the generic overload wins and stringifies the handle
471 return setProperty (property, static_cast<const ToolHandle<T2>&> (value));
472 }
473
474
475
476 template<typename T> template<typename T2>
477 StatusCode AnaToolHandle<T> ::
478 setProperty (const std::string& property,
479 const AnaToolHandle<T2>& value)
480 {
481 using namespace msgToolHandle;
482
483#ifndef NDEBUG
484 this->testInvariant ();
485 if (isInitialized())
486 {
487 ANA_MSG_FATAL ("AnaToolHandle has already been initialized: " << *this);
488 std::abort();
489 }
490#endif
491
492 // once initialized the AnaToolHandle is not that different from
493 // a regular ToolHandle and we just use it as such
494 if (value.isInitialized())
495 return setProperty (property, value.getHandle());
496
497 ANA_MSG_DEBUG ("adding sub-tool from AnaToolHandle with mode " << unsigned (value.mode()) << " and name " << value.name());
498 switch (value.mode())
499 {
500 case detail::AnaToolHandleMode::EMPTY:
501 return setProperty (property, ToolHandle<T2> ());
502 case detail::AnaToolHandleMode::CREATE_PRIVATE:
503 return m_config.addPrivateTool (property, value.config());
504 case detail::AnaToolHandleMode::CREATE_SHARED:
505 case detail::AnaToolHandleMode::RETRIEVE_SHARED:
506 m_extraInit.emplace_back ([toolhandle = value] () mutable -> StatusCode
507 {
508 ANA_CHECK (toolhandle.initialize());
509 return StatusCode::SUCCESS;
510 });
511 return m_config.setProperty (property, value.name());
512 case detail::AnaToolHandleMode::USER:
513 return setProperty (property, value.getHandle());
514 }
515 return StatusCode::FAILURE; //compiler dummy
516 }
517
518
519
520 template<typename T> template<typename T2>
521 typename std::enable_if<std::is_base_of_v<parentType_t, T2>, StatusCode>::type
522 AnaToolHandle<T> ::
523 setProperty (const std::string& property,
524 const ToolHandleArray<T2>& value)
525 {
526 using namespace msgToolHandle;
527
528#ifndef NDEBUG
529 this->testInvariant ();
530 if (isInitialized())
531 {
532 ANA_MSG_FATAL ("AnaToolHandle has already been initialized: " << *this);
533 std::abort();
534 }
535#endif
536
537 std::vector<std::string> tools;
538 // loop over toolhandles in array, strip off any parent naming
539 // and set property with the result
540 for (auto& toolHandle : value)
541 {
542 if (toolHandle.empty())
543 {
544 ANA_MSG_ERROR ("trying to initialize ToolHandleArray property " << property << " with empty handle");
545 return StatusCode::FAILURE;
546 }
547
548 tools.push_back (toolHandle.type() + "/" + toolHandle.name());
549 }
550
551 return setProperty (property, tools);
552 }
553
554
555
556 template<class T> StatusCode
557 AnaToolHandle<T> ::
558 initialize ()
559 {
560 using namespace msgToolHandle;
561
562 // ensure we don't initialize twice concurrently
563 std::lock_guard<std::recursive_mutex> lock (m_initializeMutex);
564
565#ifndef NDEBUG
566 this->testInvariant ();
567 if (isInitialized())
568 {
569 ANA_MSG_FATAL ("AnaToolHandle has already been initialized: " << *this);
570 std::abort();
571 }
572#endif
573
574 std::shared_ptr<detail::AnaToolShare> sharedTool;
575 const detail::AnaToolHandleMode mode = getMode (sharedTool);
576
577 ToolHandle<T> th (typeAndName(), m_parentPtr);
578 std::shared_ptr<void> cleanup;
579
580 switch (mode)
581 {
582 case detail::AnaToolHandleMode::EMPTY:
583 break;
584 case detail::AnaToolHandleMode::CREATE_PRIVATE:
585 for (auto& extraInit : m_extraInit)
586 ANA_CHECK (extraInit());
587 ANA_CHECK (m_config.makeTool (th, cleanup, true));
588 break;
589 case detail::AnaToolHandleMode::CREATE_SHARED:
590 ANA_CHECK (detail::AnaToolShareList::singleton().makeShare (m_name, m_config, std::move (m_extraInit), sharedTool));
591 // FALLTHROUGH
592 case detail::AnaToolHandleMode::RETRIEVE_SHARED:
593 assert (sharedTool != nullptr);
594 ANA_CHECK (detail::toolHandleCast (th, sharedTool->th()));
595#ifndef XAOD_STANDALONE
596 if (!th.empty())
597 th->release ();
598#endif
599 cleanup = sharedTool;
600 break;
601 case detail::AnaToolHandleMode::USER:
602 th = *m_handleUser;
603 if (th.empty() && !m_allowEmpty)
604 {
605 ANA_MSG_ERROR ("user configured an empty handle for a non-empty AnaToolHandle: " << *this);
606 return StatusCode::FAILURE;
607 }
608 break;
609 }
610
611 T *toolPtr = nullptr;
612 ANA_CHECK (makeToolRetrieve (toolPtr, th));
613
614 *m_handleUser = th;
615#ifndef XAOD_STANDALONE
616 if (!th.empty())
617 th->release ();
618#endif
619 m_mode = mode;
620 std::swap (m_cleanup, cleanup);
621 m_toolPtr = toolPtr;
622 m_isInitialized = true;
623
624#ifndef NDEBUG
625 this->testInvariant ();
626#endif
627 return StatusCode::SUCCESS;
628 }
629
630
631
632 template<class T> StatusCode
633 AnaToolHandle<T> ::
634 retrieve ()
635 {
636 // no invariant used
637 return initialize ();
638 }
639
640
641 template<class T> bool
642 AnaToolHandle<T> ::
643 isConfigurable () const
644 {
645 using namespace msgToolHandle;
646#ifndef NDEBUG
647 this->testInvariant ();
648#endif
649 switch (getMode())
650 {
651 case detail::AnaToolHandleMode::EMPTY:
652 case detail::AnaToolHandleMode::CREATE_PRIVATE:
653 case detail::AnaToolHandleMode::CREATE_SHARED:
654 return true;
655 case detail::AnaToolHandleMode::RETRIEVE_SHARED:
656 case detail::AnaToolHandleMode::USER:
657 return false;
658 }
659 return true; //compiler dummy
660 }
661
662
663
664 template<class T>
665#ifndef NDEBUG
666 inline
667#endif
668 bool AnaToolHandle<T> ::
669 isInitialized () const noexcept
670 {
671#ifndef NDEBUG
672 this->testInvariant ();
673#endif
674 return m_isInitialized;
675 }
676
677
678
679 template<class T> inline T *
680 AnaToolHandle<T> ::
681 operator -> ()
682 {
683 // no invariant used
684 return get ();
685 }
686
687
688
689 template<class T> inline const T *
690 AnaToolHandle<T> ::
691 operator -> () const
692 {
693 // no invariant used
694 return get ();
695 }
696
697
698
699 template<class T> inline T&
700 AnaToolHandle<T> ::
701 operator * ()
702 {
703 // no invariant used
704 return *get ();
705 }
706
707
708
709 template<class T> inline const T&
710 AnaToolHandle<T> ::
711 operator * () const
712 {
713 // no invariant used
714 return *get ();
715 }
716
717
718
719 template<class T> inline T*
720 AnaToolHandle<T> ::
721 get ()
722 {
723 using namespace msgToolHandle;
724
725#ifndef NDEBUG
726 this->testInvariant ();
727#endif
728
729 if (m_isInitialized.load())
730 return m_toolPtr;
731
732 {
733 std::lock_guard<std::recursive_mutex> lock (m_initializeMutex);
734 if (!m_isInitialized)
735 ANA_CHECK_THROW (initialize());
736 assert (m_isInitialized);
737 }
738 return m_toolPtr;
739 }
740
741
742
743 template<class T> inline const T*
744 AnaToolHandle<T> ::
745 get () const
746 {
747 AnaToolHandle<T>* this_nc ATLAS_THREAD_SAFE = const_cast<AnaToolHandle<T>*>(this);
748 return this_nc->get();
749 }
750
751
752
753 template <class T> template<typename T2> void
754 AnaToolHandle<T> ::
755 declarePropertyFor (T2 *tool, const std::string& name,
756 const std::string& description)
757 {
758 using namespace msgToolHandle;
759#ifndef NDEBUG
760 this->testInvariant ();
761 if (isInitialized())
762 {
763 ANA_MSG_FATAL ("can't declare tool handle " << *this << " as property " << name << " after tool has been instantiated");
764 std::abort ();
765 }
766#endif
767
768 if (m_parentPtr != nullptr && m_parentPtr != tool)
769 {
770 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());
771 std::abort ();
772 }
773 if (m_originalTypeAndName.empty())
774 m_originalTypeAndName = m_handleUser->typeAndName ();
775 ANA_CHECK_THROW (tool->declareProperty (name, *m_handleUser, description));
776 }
777
778
779
780
781
782
783 template <class T> const ToolHandle<T>&
784 AnaToolHandle<T> ::
785 getHandle () const noexcept
786 {
787#ifndef NDEBUG
788 this->testInvariant ();
789#endif
790 return *m_handleUser;
791 }
792
793
794
795 template <class T> bool
796 AnaToolHandle<T> ::
797 isUserConfigured () const
798 {
799 using namespace msgToolHandle;
800#ifndef NDEBUG
801 this->testInvariant ();
802#endif
803
804 // getMode can throw an exception (from dereferencing the ToolSvc handle),
805 // so this function is not noexcept.
806 switch (getMode())
807 {
808 case detail::AnaToolHandleMode::EMPTY:
809 case detail::AnaToolHandleMode::CREATE_PRIVATE:
810 case detail::AnaToolHandleMode::CREATE_SHARED:
811 return false;
812 case detail::AnaToolHandleMode::RETRIEVE_SHARED:
813 case detail::AnaToolHandleMode::USER:
814 return true;
815 }
816 return false; //compiler dummy
817 }
818
819
820
821 template<class T> std::string
822 AnaToolHandle<T> ::
823 fullName () const
824 {
825#ifndef NDEBUG
826 this->testInvariant ();
827#endif
828#ifndef XAOD_STANDALONE
829 return m_handleUser->parentName() + "." + name();
830#else
831 std::string toolName;
832 if (m_parentPtr)
833 toolName = m_parentPtr->name() + "." + name();
834 else
835 toolName = "ToolSvc." + name();
836 return toolName;
837#endif
838 }
839
840
841
842 template<class T> detail::AnaToolHandleMode AnaToolHandle<T> ::
843 getMode (std::shared_ptr<detail::AnaToolShare>& sharedTool) const
844 {
845 using namespace msgToolHandle;
846#ifndef NDEBUG
847 this->testInvariant ();
848#endif
849
850 assert (!m_isInitialized);
851
852 if (m_handleUser->isSet())
853 return detail::AnaToolHandleMode::USER;
854
855 if (m_config.empty() && m_name.empty())
856 return detail::AnaToolHandleMode::EMPTY;
857
858 if (!m_originalTypeAndName.empty() &&
859 m_handleUser->typeAndName() != m_originalTypeAndName)
860 return detail::AnaToolHandleMode::USER;
861
862#ifdef XAOD_STANDALONE
863 if (m_parentPtr != nullptr)
864 {
865 if (m_handleUser->parentName() != m_parentPtr->name())
866 return detail::AnaToolHandleMode::USER;
867 } else
868 {
869 if (m_handleUser->parentName() != "ToolSvc")
870 return detail::AnaToolHandleMode::USER;
871 }
872#endif
873
874 if (isPublic())
875 {
876 if ((sharedTool = detail::AnaToolShareList::singleton()
877 .getShare (name())))
878 return detail::AnaToolHandleMode::RETRIEVE_SHARED;
879#ifdef XAOD_STANDALONE
880 /// \todo check whether this is actually what we want to do
881 if (ToolStore::contains<T> (m_handleUser->name()))
882 return detail::AnaToolHandleMode::USER;
883#endif
884 }
885
886#ifndef XAOD_STANDALONE
887 //for athena, all we do here is check if the tool already exists
888 interfaceType_t *tool = nullptr;
889 if( detail::toolExists( fullName(), tool ) )
890 return detail::AnaToolHandleMode::USER;
891
892 if (detail::hasPropertiesInCatalogue (fullName()))
893 return detail::AnaToolHandleMode::USER;
894#endif
895
896 if (m_config.empty() && !m_handleUser->typeAndName().empty() && (m_handleUser->type() != this->type() || m_handleUser->name() != this->name()))
897 return detail::AnaToolHandleMode::USER;
898
899 if (isPublic())
900 return detail::AnaToolHandleMode::CREATE_SHARED;
901 else
902 return detail::AnaToolHandleMode::CREATE_PRIVATE;
903 }
904
905
906
907 template<class T> detail::AnaToolHandleMode AnaToolHandle<T> ::
908 getMode () const
909 {
910 if (m_isInitialized)
911 return m_mode;
912
913 std::shared_ptr<detail::AnaToolShare> sharedTool;
914 return getMode (sharedTool);
915 }
916
917
918
919 template<class T> std::string AnaToolHandle<T> ::
920 typeAndName () const
921 {
922#ifndef NDEBUG
923 this->testInvariant ();
924#endif
925 return m_config.typeAndName();
926 }
927
928
929
930 template<class T> void AnaToolHandle<T> ::
931 setType (std::string val_type) noexcept
932 {
933 using namespace msgToolHandle;
934#ifndef NDEBUG
935 this->testInvariant ();
936 if (isInitialized())
937 {
938 ANA_MSG_FATAL ("AnaToolHandle has already been initialized: " << *this);
939 std::abort();
940 }
941#endif
942
943 m_config.setType (std::move (val_type));
944 if (m_originalTypeAndName.empty() &&
945 !this->type().empty() && !this->name().empty())
946 m_handleUser->setTypeAndName (this->type() + "/" + this->name());
947
948#ifndef NDEBUG
949 this->testInvariant ();
950#endif
951 }
952
953
954
955 template<class T> void AnaToolHandle<T> ::
956 setName (std::string val_name) noexcept
957 {
958 using namespace msgToolHandle;
959#ifndef NDEBUG
960 this->testInvariant ();
961 if (isInitialized())
962 {
963 ANA_MSG_FATAL ("AnaToolHandle has already been initialized: " << *this);
964 std::abort();
965 }
966#endif
967
968 m_config.setName (val_name);
969 m_name = std::move (val_name);
970 if (m_originalTypeAndName.empty() &&
971 !this->type().empty() && !this->name().empty())
972 m_handleUser->setTypeAndName (this->type() + "/" + this->name());
973
974#ifndef NDEBUG
975 this->testInvariant ();
976#endif
977 }
978
979
980
981 template<class T> void AnaToolHandle<T> ::
982 setTypeAndName (const std::string& val_typeAndName)
983 {
984 using namespace msgToolHandle;
985#ifndef NDEBUG
986 if (isInitialized())
987 {
988 ANA_MSG_FATAL ("AnaToolHandle has already been initialized: " << *this);
989 std::abort();
990 }
991#endif
992 auto split = val_typeAndName.find ("/");
993 if (split != std::string::npos)
994 {
995 setTypeAndName (val_typeAndName.substr (0, split),
996 val_typeAndName.substr (split+1));
997 } else
998 {
999 setTypeAndName (val_typeAndName, val_typeAndName);
1000 }
1001 }
1002
1003
1004
1005 template<class T> void AnaToolHandle<T> ::
1006 setTypeAndName (std::string val_type, std::string val_name) noexcept
1007 {
1008 using namespace msgToolHandle;
1009#ifndef NDEBUG
1010 if (isInitialized())
1011 {
1012 ANA_MSG_FATAL ("AnaToolHandle has already been initialized: " << *this);
1013 std::abort();
1014 }
1015#endif
1016 setType (std::move (val_type));
1017 setName (std::move (val_name));
1018 }
1019
1020
1021
1022 template<class T> StatusCode AnaToolHandle<T> ::
1023 makeToolRetrieve (T*& toolPtr, ToolHandle<T>& toolHandle) const
1024 {
1025 using namespace msgToolHandle;
1026
1027 if (toolHandle.empty())
1028 {
1029 toolPtr = nullptr;
1030 return StatusCode::SUCCESS;
1031 }
1032
1033 try
1034 {
1035 toolPtr = toolHandle.operator->();
1036 if (toolPtr == nullptr)
1037 {
1038 ANA_MSG_ERROR ("failed to retrieve tool from tool handle " << *m_handleUser);
1039 return StatusCode::FAILURE;
1040 }
1041 return StatusCode::SUCCESS;
1042 } catch (std::exception& e)
1043 {
1044 ANA_MSG_ERROR ("encountered exception during tool retrieval (" << toolHandle << "): " << e.what());
1045 return StatusCode::FAILURE;
1046 }
1047 }
1048
1049
1050
1051 template<class T> detail::AnaToolHandleMode AnaToolHandle<T> ::
1052 mode () const
1053 {
1054#ifndef NDEBUG
1055 this->testInvariant ();
1056#endif
1057 return getMode ();
1058 }
1059
1060
1061
1062 template<class T> const AsgToolConfig& AnaToolHandle<T> ::
1063 config () const
1064 {
1065#ifndef NDEBUG
1066 this->testInvariant ();
1067#endif
1068 return m_config;
1069 }
1070
1071
1072
1073 template<class T> bool AnaToolHandle<T> ::
1074 allowEmpty () const noexcept
1075 {
1076#ifndef NDEBUG
1077 this->testInvariant ();
1078#endif
1079 return m_allowEmpty;
1080 }
1081
1082
1083
1084 template<class T> void AnaToolHandle<T> ::
1085 setAllowEmpty (bool val_allowEmpty) noexcept
1086 {
1087 using namespace msgToolHandle;
1088#ifndef NDEBUG
1089 this->testInvariant ();
1090 if (isInitialized())
1091 {
1092 ANA_MSG_FATAL ("AnaToolHandle has already been initialized: " << *this);
1093 std::abort();
1094 }
1095#endif
1096 m_allowEmpty = val_allowEmpty;
1097 }
1098}
1099
1100#endif // ASGTOOLS_ANATOOLHANDLE_ICC