ATLAS Offline Software
AnaToolHandle.icc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2021 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;
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  tmp->release();
292 #endif
293  *m_handleUser = *that.m_handleUser;
294  *that.m_handleUser = tmp;
295  }
296  m_originalTypeAndName.swap (that.m_originalTypeAndName);
297  {
298  const auto tmp = m_isInitialized.load();
299  m_isInitialized = that.m_isInitialized.load();
300  that.m_isInitialized = tmp;
301  }
302  std::swap (m_toolPtr, that.m_toolPtr);
303  std::swap (m_mode, that.m_mode);
304  std::swap (m_allowEmpty, that.m_allowEmpty);
305 
306 #ifndef NDEBUG
307  testInvariant ();
308  that.testInvariant ();
309 #endif
310  }
311 
312 
313 
314  template<class T> AnaToolHandle<T>& AnaToolHandle<T> ::
315  operator = (AnaToolHandle<T>&& that)
316  {
317  // no invariant used
318  swap (that);
319  return *this;
320  }
321 
322 
323 
324  template<class T> AnaToolHandle<T> ::
325  ~AnaToolHandle () noexcept
326  {
327  using namespace msgToolHandle;
328 #ifndef NDEBUG
329  this->testInvariant ();
330 #endif
331  }
332 
333 
334  template<class T> bool
335  AnaToolHandle<T> ::
336  empty () const
337  {
338 #ifndef NDEBUG
339  this->testInvariant ();
340 #endif
341  switch (getMode())
342  {
343  case detail::AnaToolHandleMode::EMPTY:
344  return true;
345  case detail::AnaToolHandleMode::CREATE_PRIVATE:
346  case detail::AnaToolHandleMode::CREATE_SHARED:
347  case detail::AnaToolHandleMode::RETRIEVE_SHARED:
348  return false;
349  case detail::AnaToolHandleMode::USER:
350  return m_handleUser->empty();
351  }
352  return false; //compiler dummy
353  }
354 
355 
356 
357  template<class T> inline bool AnaToolHandle<T> ::
358  isPublic () const noexcept
359  {
360 #ifndef NDEBUG
361  this->testInvariant ();
362 #endif
363  return m_parentPtr == nullptr;
364  }
365 
366 
367 
368  template<class T> inline const std::string& AnaToolHandle<T> ::
369  type () const noexcept
370  {
371 #ifndef NDEBUG
372  this->testInvariant ();
373 #endif
374  return m_config.type();
375  }
376 
377 
378 
379  template<class T> inline const std::string&
380  AnaToolHandle<T> ::
381  name () const noexcept
382  {
383 #ifndef NDEBUG
384  this->testInvariant ();
385 #endif
386  return m_name;
387  }
388 
389 
390 
391  template<typename T> template<typename T2>
392  StatusCode AnaToolHandle<T> ::
393  setProperty (const std::string& property, const T2& value)
394  {
395  using namespace msgToolHandle;
396 
397 #ifndef NDEBUG
398  this->testInvariant ();
399  if (isInitialized())
400  {
401  ANA_MSG_FATAL ("AnaToolHandle has already been initialized: " << *this);
402  std::abort();
403  }
404 #endif
405 
406  return m_config.setProperty (property, value);
407  }
408 
409 
410 
411  template<typename T> template<typename T2>
412  typename std::enable_if<std::is_base_of_v<parentType_t, T2>, StatusCode>::type
413  AnaToolHandle<T> ::
414  setProperty (const std::string& property,
415  const ToolHandle<T2>& value)
416  {
417  using namespace msgToolHandle;
418 
419 #ifndef NDEBUG
420  this->testInvariant ();
421  if (isInitialized())
422  {
423  ANA_MSG_FATAL ("AnaToolHandle has already been initialized: " << *this);
424  std::abort();
425  }
426 #endif
427 
428  ANA_MSG_DEBUG ("adding sub-tool from ToolHandle: " << value);
429  if (value.empty())
430  return setProperty (property, std::string ());
431 #ifndef XAOD_STANDALONE
432  else if (value.isPublic())
433 #else
434  else if (value.parentName() == "ToolSvc")
435 #endif
436  {
437  return setProperty (property,
438  value.type() + "/" + value.name());
439  } else
440  {
441 #ifndef XAOD_STANDALONE
442  AsgToolConfig subToolConfig;
443  ANA_CHECK (detail::readToolConfig (subToolConfig, value.parentName() + "." + value.name()));
444  ANA_CHECK (m_config.addPrivateTool (property, subToolConfig));
445  return StatusCode::SUCCESS;
446 #else
447  return setProperty (property, value.name());
448 #endif
449  }
450  }
451 
452 
453 
454  template<typename T> template<typename T2>
455  StatusCode AnaToolHandle<T> ::
456  setProperty (const std::string& property,
457  const AnaToolHandle<T2>& value)
458  {
459  using namespace msgToolHandle;
460 
461 #ifndef NDEBUG
462  this->testInvariant ();
463  if (isInitialized())
464  {
465  ANA_MSG_FATAL ("AnaToolHandle has already been initialized: " << *this);
466  std::abort();
467  }
468 #endif
469 
470  // once initialized the AnaToolHandle is not that different from
471  // a regular ToolHandle and we just use it as such
472  if (value.isInitialized())
473  return setProperty (property, value.getHandle());
474 
475  ANA_MSG_DEBUG ("adding sub-tool from AnaToolHandle with mode " << unsigned (value.mode()) << " and name " << value.name());
476  switch (value.mode())
477  {
478  case detail::AnaToolHandleMode::EMPTY:
479  return setProperty (property, ToolHandle<T2> ());
480  case detail::AnaToolHandleMode::CREATE_PRIVATE:
481  return m_config.addPrivateTool (property, value.config());
482  case detail::AnaToolHandleMode::CREATE_SHARED:
483  case detail::AnaToolHandleMode::RETRIEVE_SHARED:
484  m_extraInit.emplace_back ([toolhandle = value] () mutable -> StatusCode
485  {
486  ANA_CHECK (toolhandle.initialize());
487  return StatusCode::SUCCESS;
488  });
489  return m_config.setProperty (property, value.name());
490  case detail::AnaToolHandleMode::USER:
491  return setProperty (property, value.getHandle());
492  }
493  return StatusCode::FAILURE; //compiler dummy
494  }
495 
496 
497 
498  template<typename T> template<typename T2>
499  typename std::enable_if<std::is_base_of_v<parentType_t, T2>, StatusCode>::type
500  AnaToolHandle<T> ::
501  setProperty (const std::string& property,
502  const ToolHandleArray<T2>& value)
503  {
504  using namespace msgToolHandle;
505 
506 #ifndef NDEBUG
507  this->testInvariant ();
508  if (isInitialized())
509  {
510  ANA_MSG_FATAL ("AnaToolHandle has already been initialized: " << *this);
511  std::abort();
512  }
513 #endif
514 
515  std::vector<std::string> tools;
516  // loop over toolhandles in array, strip off any parent naming
517  // and set property with the result
518  for (auto& toolHandle : value)
519  {
520  if (toolHandle.empty())
521  {
522  ANA_MSG_ERROR ("trying to initialize ToolHandleArray property " << property << " with empty handle");
523  return StatusCode::FAILURE;
524  }
525 
526  tools.push_back (toolHandle.type() + "/" + toolHandle.name());
527  }
528 
529  return setProperty (property, tools);
530  }
531 
532 
533 
534  template<class T> StatusCode
535  AnaToolHandle<T> ::
536  initialize ()
537  {
538  using namespace msgToolHandle;
539 
540  // ensure we don't initialize twice concurrently
541  std::lock_guard<std::recursive_mutex> lock (m_initializeMutex);
542 
543 #ifndef NDEBUG
544  this->testInvariant ();
545  if (isInitialized())
546  {
547  ANA_MSG_FATAL ("AnaToolHandle has already been initialized: " << *this);
548  std::abort();
549  }
550 #endif
551 
552  std::shared_ptr<detail::AnaToolShare> sharedTool;
553  const detail::AnaToolHandleMode mode = getMode (sharedTool);
554 
555  ToolHandle<T> th (typeAndName(), m_parentPtr);
556  std::shared_ptr<void> cleanup;
557 
558  switch (mode)
559  {
560  case detail::AnaToolHandleMode::EMPTY:
561  break;
562  case detail::AnaToolHandleMode::CREATE_PRIVATE:
563  for (auto& extraInit : m_extraInit)
564  ANA_CHECK (extraInit());
565  ANA_CHECK (m_config.makeTool (th, cleanup, true));
566  break;
567  case detail::AnaToolHandleMode::CREATE_SHARED:
568  ANA_CHECK (detail::AnaToolShareList::singleton().makeShare (m_name, m_config, std::move (m_extraInit), sharedTool));
569  // FALLTHROUGH
570  case detail::AnaToolHandleMode::RETRIEVE_SHARED:
571  assert (sharedTool != nullptr);
572  ANA_CHECK (detail::toolHandleCast (th, sharedTool->th()));
573 #ifndef XAOD_STANDALONE
574  if (!th.empty())
575  th->release ();
576 #endif
577  cleanup = sharedTool;
578  break;
579  case detail::AnaToolHandleMode::USER:
580  th = *m_handleUser;
581  if (th.empty() && !m_allowEmpty)
582  {
583  ANA_MSG_ERROR ("user configured an empty handle for a non-empty AnaToolHandle: " << *this);
584  return StatusCode::FAILURE;
585  }
586  break;
587  }
588 
589  // cppcheck-suppress constStatement; false positive
590  T *toolPtr = nullptr;
591  ANA_CHECK (makeToolRetrieve (toolPtr, th));
592 
593  *m_handleUser = th;
594 #ifndef XAOD_STANDALONE
595  if (!th.empty())
596  th->release ();
597 #endif
598  m_mode = mode;
599  std::swap (m_cleanup, cleanup);
600  m_toolPtr = toolPtr;
601  m_isInitialized = true;
602 
603 #ifndef NDEBUG
604  this->testInvariant ();
605 #endif
606  return StatusCode::SUCCESS;
607  }
608 
609 
610 
611  template<class T> StatusCode
612  AnaToolHandle<T> ::
613  retrieve ()
614  {
615  // no invariant used
616  return initialize ();
617  }
618 
619 
620  template<class T> bool
621  AnaToolHandle<T> ::
622  isConfigurable () const
623  {
624  using namespace msgToolHandle;
625 #ifndef NDEBUG
626  this->testInvariant ();
627 #endif
628  switch (getMode())
629  {
630  case detail::AnaToolHandleMode::EMPTY:
631  case detail::AnaToolHandleMode::CREATE_PRIVATE:
632  case detail::AnaToolHandleMode::CREATE_SHARED:
633  return true;
634  case detail::AnaToolHandleMode::RETRIEVE_SHARED:
635  case detail::AnaToolHandleMode::USER:
636  return false;
637  }
638  return true; //compiler dummy
639  }
640 
641 
642 
643  template<class T>
644 #ifndef NDEBUG
645  inline
646 #endif
647  bool AnaToolHandle<T> ::
648  isInitialized () const noexcept
649  {
650 #ifndef NDEBUG
651  this->testInvariant ();
652 #endif
653  return m_isInitialized;
654  }
655 
656 
657 
658  template<class T> inline T *
659  AnaToolHandle<T> ::
660  operator -> ()
661  {
662  // no invariant used
663  return get ();
664  }
665 
666 
667 
668  template<class T> inline const T *
669  AnaToolHandle<T> ::
670  operator -> () const
671  {
672  // no invariant used
673  return get ();
674  }
675 
676 
677 
678  template<class T> inline T&
679  AnaToolHandle<T> ::
680  operator * ()
681  {
682  // no invariant used
683  return *get ();
684  }
685 
686 
687 
688  template<class T> inline const T&
689  AnaToolHandle<T> ::
690  operator * () const
691  {
692  // no invariant used
693  return *get ();
694  }
695 
696 
697 
698  template<class T> inline T*
699  AnaToolHandle<T> ::
700  get ()
701  {
702  using namespace msgToolHandle;
703 
704 #ifndef NDEBUG
705  this->testInvariant ();
706 #endif
707 
708  if (m_isInitialized.load())
709  return m_toolPtr;
710 
711  std::lock_guard<std::recursive_mutex> lock (m_initializeMutex);
712  if (!m_isInitialized)
713  ANA_CHECK_THROW (initialize());
714  assert (m_isInitialized);
715  return m_toolPtr;
716  }
717 
718 
719 
720  template<class T> inline const T*
721  AnaToolHandle<T> ::
722  get () const
723  {
724  AnaToolHandle<T>* this_nc ATLAS_THREAD_SAFE = const_cast<AnaToolHandle<T>*>(this);
725  return this_nc->get();
726  }
727 
728 
729 
730  template <class T> template<typename T2> void
731  AnaToolHandle<T> ::
732  declarePropertyFor (T2 *tool, const std::string& name,
733  const std::string& description)
734  {
735  using namespace msgToolHandle;
736 #ifndef NDEBUG
737  this->testInvariant ();
738  if (isInitialized())
739  {
740  ANA_MSG_FATAL ("can't declare tool handle " << *this << " as property " << name << " after tool has been instantiated");
741  std::abort ();
742  }
743 #endif
744 
745  if (m_parentPtr != nullptr && m_parentPtr != tool)
746  {
747  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());
748  std::abort ();
749  }
750  if (m_originalTypeAndName.empty())
751  m_originalTypeAndName = m_handleUser->typeAndName ();
752  ANA_CHECK_THROW (tool->declareProperty (name, *m_handleUser, description));
753  }
754 
755 
756 
757 
758 
759 
760  template <class T> const ToolHandle<T>&
761  AnaToolHandle<T> ::
762  getHandle () const noexcept
763  {
764 #ifndef NDEBUG
765  this->testInvariant ();
766 #endif
767  return *m_handleUser;
768  }
769 
770 
771 
772  template <class T> bool
773  AnaToolHandle<T> ::
774  isUserConfigured () const noexcept
775  {
776  using namespace msgToolHandle;
777 #ifndef NDEBUG
778  this->testInvariant ();
779 #endif
780 
781  switch (getMode())
782  {
783  case detail::AnaToolHandleMode::EMPTY:
784  case detail::AnaToolHandleMode::CREATE_PRIVATE:
785  case detail::AnaToolHandleMode::CREATE_SHARED:
786  return false;
787  case detail::AnaToolHandleMode::RETRIEVE_SHARED:
788  case detail::AnaToolHandleMode::USER:
789  return true;
790  }
791  return false; //compiler dummy
792  }
793 
794 
795 
796  template<class T> std::string
797  AnaToolHandle<T> ::
798  fullName () const
799  {
800 #ifndef NDEBUG
801  this->testInvariant ();
802 #endif
803 #ifndef XAOD_STANDALONE
804  return m_handleUser->parentName() + "." + name();
805 #else
806  std::string toolName;
807  if (m_parentPtr)
808  toolName = m_parentPtr->name() + "." + name();
809  else
810  toolName = "ToolSvc." + name();
811  return toolName;
812 #endif
813  }
814 
815 
816 
817  template<class T> detail::AnaToolHandleMode AnaToolHandle<T> ::
818  getMode (std::shared_ptr<detail::AnaToolShare>& sharedTool) const
819  {
820  using namespace msgToolHandle;
821 #ifndef NDEBUG
822  this->testInvariant ();
823 #endif
824 
825  assert (!m_isInitialized);
826 
827  if (m_handleUser->isSet())
828  return detail::AnaToolHandleMode::USER;
829 
830  if (m_config.empty() && m_name.empty())
831  return detail::AnaToolHandleMode::EMPTY;
832 
833  if (!m_originalTypeAndName.empty() &&
834  m_handleUser->typeAndName() != m_originalTypeAndName)
835  return detail::AnaToolHandleMode::USER;
836 
837 #ifdef XAOD_STANDALONE
838  if (m_parentPtr != nullptr)
839  {
840  if (m_handleUser->parentName() != m_parentPtr->name())
841  return detail::AnaToolHandleMode::USER;
842  } else
843  {
844  if (m_handleUser->parentName() != "ToolSvc")
845  return detail::AnaToolHandleMode::USER;
846  }
847 #endif
848 
849  if (isPublic())
850  {
851  if ((sharedTool = detail::AnaToolShareList::singleton()
852  .getShare (name())))
853  return detail::AnaToolHandleMode::RETRIEVE_SHARED;
854 #ifdef XAOD_STANDALONE
855  /// \todo check whether this is actually what we want to do
856  if (ToolStore::contains<T> (m_handleUser->name()))
857  return detail::AnaToolHandleMode::USER;
858 #endif
859  }
860 
861 #ifndef XAOD_STANDALONE
862  //for athena, all we do here is check if the tool already exists
863  interfaceType_t *tool = nullptr;
864  if( detail::toolExists( fullName(), tool ) )
865  return detail::AnaToolHandleMode::USER;
866 
867  if (detail::hasPropertiesInCatalogue (fullName()))
868  return detail::AnaToolHandleMode::USER;
869 #endif
870 
871  if (m_config.empty() && !m_handleUser->typeAndName().empty() && (m_handleUser->type() != this->type() || m_handleUser->name() != this->name()))
872  return detail::AnaToolHandleMode::USER;
873 
874  if (isPublic())
875  return detail::AnaToolHandleMode::CREATE_SHARED;
876  else
877  return detail::AnaToolHandleMode::CREATE_PRIVATE;
878  }
879 
880 
881 
882  template<class T> detail::AnaToolHandleMode AnaToolHandle<T> ::
883  getMode () const
884  {
885  if (m_isInitialized)
886  return m_mode;
887 
888  std::shared_ptr<detail::AnaToolShare> sharedTool;
889  return getMode (sharedTool);
890  }
891 
892 
893 
894  template<class T> std::string AnaToolHandle<T> ::
895  typeAndName () const
896  {
897 #ifndef NDEBUG
898  this->testInvariant ();
899 #endif
900  return m_config.typeAndName();
901  }
902 
903 
904 
905  template<class T> void AnaToolHandle<T> ::
906  setType (std::string val_type) noexcept
907  {
908  using namespace msgToolHandle;
909 #ifndef NDEBUG
910  this->testInvariant ();
911  if (isInitialized())
912  {
913  ANA_MSG_FATAL ("AnaToolHandle has already been initialized: " << *this);
914  std::abort();
915  }
916 #endif
917 
918  m_config.setType (std::move (val_type));
919  if (m_originalTypeAndName.empty() &&
920  !this->type().empty() && !this->name().empty())
921  m_handleUser->setTypeAndName (this->type() + "/" + this->name());
922 
923 #ifndef NDEBUG
924  this->testInvariant ();
925 #endif
926  }
927 
928 
929 
930  template<class T> void AnaToolHandle<T> ::
931  setName (std::string val_name) 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.setName (val_name);
944  m_name = std::move (val_name);
945  if (m_originalTypeAndName.empty() &&
946  !this->type().empty() && !this->name().empty())
947  m_handleUser->setTypeAndName (this->type() + "/" + this->name());
948 
949 #ifndef NDEBUG
950  this->testInvariant ();
951 #endif
952  }
953 
954 
955 
956  template<class T> void AnaToolHandle<T> ::
957  setTypeAndName (const std::string& val_typeAndName)
958  {
959  using namespace msgToolHandle;
960 #ifndef NDEBUG
961  if (isInitialized())
962  {
963  ANA_MSG_FATAL ("AnaToolHandle has already been initialized: " << *this);
964  std::abort();
965  }
966 #endif
967  auto split = val_typeAndName.find ("/");
968  if (split != std::string::npos)
969  {
970  setTypeAndName (val_typeAndName.substr (0, split),
971  val_typeAndName.substr (split+1));
972  } else
973  {
974  setTypeAndName (val_typeAndName, val_typeAndName);
975  }
976  }
977 
978 
979 
980  template<class T> void AnaToolHandle<T> ::
981  setTypeAndName (std::string val_type, std::string val_name) noexcept
982  {
983  using namespace msgToolHandle;
984 #ifndef NDEBUG
985  if (isInitialized())
986  {
987  ANA_MSG_FATAL ("AnaToolHandle has already been initialized: " << *this);
988  std::abort();
989  }
990 #endif
991  setType (std::move (val_type));
992  setName (std::move (val_name));
993  }
994 
995 
996 
997  template<class T> StatusCode AnaToolHandle<T> ::
998  makeToolRetrieve (T*& toolPtr, ToolHandle<T>& toolHandle) const
999  {
1000  using namespace msgToolHandle;
1001 
1002  if (toolHandle.empty())
1003  {
1004  toolPtr = nullptr;
1005  return StatusCode::SUCCESS;
1006  }
1007 
1008  try
1009  {
1010  toolPtr = toolHandle.operator->();
1011  if (toolPtr == nullptr)
1012  {
1013  ANA_MSG_ERROR ("failed to retrieve tool from tool handle " << *m_handleUser);
1014  return StatusCode::FAILURE;
1015  }
1016  return StatusCode::SUCCESS;
1017  } catch (std::exception& e)
1018  {
1019  ANA_MSG_ERROR ("encountered exception during tool retrieval (" << toolHandle << "): " << e.what());
1020  return StatusCode::FAILURE;
1021  }
1022  }
1023 
1024 
1025 
1026  template<class T> detail::AnaToolHandleMode AnaToolHandle<T> ::
1027  mode () const
1028  {
1029 #ifndef NDEBUG
1030  this->testInvariant ();
1031 #endif
1032  return getMode ();
1033  }
1034 
1035 
1036 
1037  template<class T> const AsgToolConfig& AnaToolHandle<T> ::
1038  config () const
1039  {
1040 #ifndef NDEBUG
1041  this->testInvariant ();
1042 #endif
1043  return m_config;
1044  }
1045 
1046 
1047 
1048  template<class T> bool AnaToolHandle<T> ::
1049  allowEmpty () const noexcept
1050  {
1051 #ifndef NDEBUG
1052  this->testInvariant ();
1053 #endif
1054  return m_allowEmpty;
1055  }
1056 
1057 
1058 
1059  template<class T> void AnaToolHandle<T> ::
1060  setAllowEmpty (bool val_allowEmpty) noexcept
1061  {
1062  using namespace msgToolHandle;
1063 #ifndef NDEBUG
1064  this->testInvariant ();
1065  if (isInitialized())
1066  {
1067  ANA_MSG_FATAL ("AnaToolHandle has already been initialized: " << *this);
1068  std::abort();
1069  }
1070 #endif
1071  m_allowEmpty = val_allowEmpty;
1072  }
1073 }
1074 
1075 #endif // ASGTOOLS_ANATOOLHANDLE_ICC