ATLAS Offline Software
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 
18 namespace 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