diff --git a/Control/AthToolSupport/AsgTools/AsgTools/AnaToolHandle.h b/Control/AthToolSupport/AsgTools/AsgTools/AnaToolHandle.h
index ed8e8bbbe33e0c16673b4aaddda70c413012f9f5..a4af1643eb93ad1282f6660a2f2aff33485dfb21 100644
--- a/Control/AthToolSupport/AsgTools/AsgTools/AnaToolHandle.h
+++ b/Control/AthToolSupport/AsgTools/AsgTools/AnaToolHandle.h
@@ -17,20 +17,343 @@
 #include <AsgTools/AsgTool.h>
 #include <AsgTools/Deprecated.h>
 #include <AsgTools/ToolHandle.h>
+#include <atomic>
+#include <list>
 #include <map>
+#include <mutex>
 
 namespace asg
 {
 #ifdef ROOTCORE
    typedef asg::AsgTool parentType_t;
+   typedef IAsgTool interfaceType_t;
 #else
    typedef INamedInterface parentType_t;
    typedef IAlgTool interfaceType_t;
 #endif
 
-
   template<class T> class AnaToolHandle;
 
+  namespace detail
+  {
+    class AnaToolShare;
+
+    /// \brief a class maintaining a list of cleanups to be performed
+    /// when releasing a tool.
+
+    class AnaToolCleanup
+    {
+      //
+      // public interface
+      //
+
+      /// \brief standard swap
+      /// \par Guarantee
+      ///   no-fail
+    public:
+      void swap (AnaToolCleanup& that);
+
+
+      /// \brief add a cleanup to perform
+      ///
+      /// Normally this is added to the end of the list of cleanups,
+      /// but by passing post as false, you can also add it at the
+      /// beginning.
+      ///
+      /// \par Guarantee
+      ///   basic
+      /// \par Failures
+      ///   out of memory II
+    public:
+      void addCleanup (AnaToolCleanup val_cleanup, bool post = true);
+
+      /// \copydoc addCleanup
+    public:
+      void addCleanup (const std::shared_ptr<void>& val_cleanup,
+		       bool post = true);
+
+
+
+      //
+      // private interface
+      //
+
+    private:
+      std::list<std::shared_ptr<void> > m_cleanup;
+    };
+
+
+
+    /// \brief the base class for classes holding property values for
+    /// AnaToolHandle
+
+    class AnaToolProperty
+    {
+      //
+      // public interface
+      //
+
+      /// \brief standard default constructor for base class
+      /// \par Guarantee
+      ///   no-fail
+    public:
+      virtual ~AnaToolProperty () noexcept = default;
+
+#ifdef ROOTCORE
+      /// \brief apply the property to the given tool in RootCore
+      /// \par Guarantee
+      ///   basic
+      /// \par Failures
+      ///   unknown property\n
+      ///   invalid property type/value\n
+      ///   out of memory II
+    public:
+      virtual StatusCode
+      applyPropertyRootCore (AsgTool& tool, const std::string& name,
+			     AnaToolCleanup& cleanup)
+	const = 0;
+#endif
+
+#ifndef ROOTCORE
+      /// \brief store the property in the configuration service in
+      /// Athena
+      /// \par Guarantee
+      ///   basic
+      /// \par Failures
+      ///   out of memory II
+    public:
+      virtual StatusCode
+      applyPropertyAthena (const std::string& toolName,
+			   const std::string& name,
+			   AnaToolCleanup& cleanup)
+	const = 0;
+#endif
+    };
+
+
+
+    /// \brief the complete configuration for a tool
+    ///
+    /// This is very much a-kin to the python configurables used
+    /// inside Athena (thanks Steve Farrell for the analogy).
+    /// However, so far this is mostly an internal helper class for
+    /// the \ref AnaToolHandle implementation.
+
+    class AnaToolConfig
+    {
+      //
+      // public interface
+      //
+
+      /// \brief standard swap
+      /// \par Guarantee
+      ///   no-fail
+    public:
+      void swap (AnaToolConfig& that) noexcept;
+
+
+      /// \brief whether we contain no properties
+      /// \par Guarantee
+      ///   no-fail
+    public:
+      bool empty () const noexcept;
+
+
+      /// \brief the type of the tool to create
+      /// \par Guarantee
+      ///   no-fail
+    public:
+      const std::string& type () const noexcept;
+
+      /// \brief set the value of \ref type
+      /// \par Guarantee
+      ///   no-fail
+    public:
+      void setType (std::string type) noexcept;
+
+#ifdef ROOTCORE
+      /// \brief register the new of the given type as factory
+      ///
+      /// If this is set, it is used instead of \ref type to allocate
+      /// the tool.  This is mostly meant as a stop-gap solution for
+      /// tools which either do not have a dictionary, or which have a
+      /// class structure incompatible with instantiation via the
+      /// dictionary.
+      /// \par Guarantee
+      ///   strong
+      /// \par Failures
+      ///   out of memory I
+    public:
+      template<typename Type>
+      void registerNew ();
+#endif
+
+
+      /// \brief set the property with the given name in the same
+      /// fashion as \ref AnaToolHandle::setProperty
+      /// \par Guarantee
+      ///   strong
+      /// \par Failures
+      ///   out of memory II\n
+      ///   no way to handle value
+    public:
+      template<typename Type> StatusCode
+      setProperty (const std::string& val_name, const Type& val_value);
+
+      /// \copydoc setProperty
+    public:
+      template<typename Type> StatusCode
+      setProperty (const std::string& val_name,
+		   const AnaToolHandle<Type>& val_value);
+
+#ifndef ROOTCORE
+      /// \copydoc setProperty
+    public:
+      template<typename Type> StatusCode
+      setProperty (const std::string& val_name,
+		   const ToolHandle<Type>& val_value);
+
+      /// \copydoc setProperty
+    public:
+      template<typename Type> StatusCode
+      setProperty (const std::string& val_name,
+		   const ToolHandleArray<Type>& val_value);
+#endif
+
+
+      /// \copydoc setProperty
+    public:
+      StatusCode
+      setProperty (const std::string& val_name,
+		   const char *val_value);
+
+
+      /// \brief add/set the property with the given name
+      /// \par Guarantee
+      ///   strong
+      /// \par Failures
+      ///   out of memory II
+    public:
+      void addProperty (const std::string& name,
+			const std::shared_ptr<AnaToolProperty>& property);
+
+
+      /// \brief make a configured and initialized tool
+      /// \par Guarantee
+      ///   strong
+      /// \par Failures
+      ///   tool creation failures
+    public:
+      template<typename ToolType> StatusCode
+      makeTool (const std::string& name,
+                parentType_t *parent,
+		ToolHandle<ToolType>& th,
+		AnaToolCleanup& cleanup) const;
+
+
+      /// \brief make a configured and initialized tool of the basic type
+      /// \par Guarantee
+      ///   strong
+      /// \par Failures
+      ///   tool creation failures
+    public:
+      StatusCode
+      makeBaseTool (const std::string& name,
+                    parentType_t *parent,
+                    ToolHandle<interfaceType_t>& th,
+                    AnaToolCleanup& cleanup) const;
+
+
+#ifndef ROOTCORE
+      /// \brief store the properties in the configuration service in
+      /// Athena
+      /// \par Guarantee
+      ///   basic
+      /// \par Failures
+      ///   out of memory II
+    public:
+      StatusCode
+      applyPropertiesAthena (const std::string& toolName,
+			     AnaToolCleanup& cleanup) const;
+#endif
+
+
+
+      //
+      // private interface
+      //
+
+      /// \brief the value of \ref type
+    private:
+      std::string m_type;
+
+      /// \brief the factory to use, if we have one
+    private:
+      std::function<StatusCode (AsgTool*&, const std::string&)> m_factory;
+
+      /// \brief the list of all properties stored
+    private:
+      std::map<std::string,std::shared_ptr<AnaToolProperty> > m_properties;
+
+
+#ifdef ROOTCORE
+      /// \brief create, configure and initialize the tool (in
+      /// RootCore)
+      /// \par Guarantee
+      ///   strong
+      /// \par Failures
+      ///   tool creation/initialization failures
+    private:
+      StatusCode
+      makeToolRootCore (const std::string& toolName, IAsgTool*& toolPtr,
+			detail::AnaToolCleanup& cleanup) const;
+#endif
+
+
+#ifdef ROOTCORE
+      /// \brief allocate the tool
+      /// \par Guarantee
+      ///   basic
+      /// \par Failures
+      ///   tool allocation failures
+    private:
+      StatusCode
+      allocateTool (AsgTool*& toolPtr, const std::string& toolName) const;
+#endif
+    };
+
+
+
+    /// \brief the mode with which an \ref AnaToolHandle object is
+    /// initialized
+
+    enum class AnaToolHandleMode
+    {
+      /// do not create a tool
+      ///
+      /// this can be either explicitly an empty tool handle set by
+      /// the user, or an AnaToolHandle that was never configured in
+      /// the first place.
+      EMPTY,
+
+      /// create a private tool normally
+      CREATE_PRIVATE,
+
+      /// create a shared tool normally
+      CREATE_SHARED,
+
+      /// retrieve a shared tool
+      RETRIEVE_SHARED,
+
+      /// retrieve a tool from the user tool handle
+      ///
+      /// this can still refer to a tool handle that is empty, though
+      /// usually it will point to an actual tool
+      USER
+    };
+  }
+
+
 
   /// \brief standard output operator
   /// \par Guarantee
@@ -71,26 +394,27 @@ namespace asg
   /// off by the complexity of Athena configuration.
   ///
   ///
-  /// Conceptually this tools tries to model an std::unique_ptr or
-  /// std::shared_ptr, for which calls to new, setProperty and
-  /// initialize have been wrapped to make them dual-use as well as
-  /// safer to use.  If a parent tool is specified, the tool is
-  /// private (and this tool handle is modeled after unique_ptr).  If
-  /// no parent tool is specified, the tool is public/shared (and this
-  /// tool handle is modeled after shared_ptr).
+  /// The basic interface is a mix between the ToolHandle interface
+  /// for accessing the tool, and the AsgTool interface for
+  /// configuring/initializing the tools.  In addition it allows to
+  /// set this ToolHandle as a property on another configurable, to
+  /// allow configuring it via the standard configuration mechanisms.
   ///
-  /// In public/shared mode, if you create and initialize one tool it
-  /// is then available for use by other tool handles registered with
-  /// the same name and type.  The subsequent tool handles with that
-  /// name will then automatically pick up the tool in the
-  /// configuration set by the first tool handle.  The user still has
-  /// to call initialize() on the tool handle before using the tool.
-  /// While it is allowed to call setProperty* method on those tool
-  /// handles these calls will be effectively ignored.  The net effect
-  /// of that is that as a user of a handle for a shared tool you
-  /// don't have to worry about whether you are the one creating the
-  /// tool or just using it, you just initialize the tool handle in
-  /// the same way.
+  /// If a parent tool is specified, the tool is private (and this
+  /// tool handle is modeled after unique_ptr).  If no parent tool is
+  /// specified, the tool is public/shared (and this tool handle is
+  /// modeled after shared_ptr).  In public/shared mode, if you create
+  /// and initialize one tool it is then available for use by other
+  /// tool handles registered with the same name and type.  The
+  /// subsequent tool handles with that name will then automatically
+  /// pick up the tool in the configuration set by the first tool
+  /// handle.  The user still has to call initialize() on the tool
+  /// handle before using the tool.  While it is allowed to call the
+  /// setProperty method on those tool handles these calls will be
+  /// effectively ignored.  The net effect of that is that as a user
+  /// of a handle for a shared tool you don't have to worry about
+  /// whether you are the one creating the tool or just using it, you
+  /// just initialize the tool handle in the same way.
   ///
   /// The tool handle can also be declared as a property on the parent
   /// tool by using the ToolHandle provided via its handle member
@@ -104,6 +428,24 @@ namespace asg
   /// you can just write your code as if the user didn't configure
   /// your tool handle and if the user does, the tool handle will
   /// automatically switch over.
+  ///
+  ///
+  /// There are a number of ways of how a tool can be created/accessed
+  /// through an AnaToolHandle (in *increasing* order of precedence):
+  /// - normally an AnaToolHandle will create its tool based on the
+  ///   configured type and properties under the configured name.
+  /// - if an AnaToolHandle has been created without a parent (i.e. as
+  ///   a public tool) and another AnaToolHandle already has created a
+  ///   public tool with the same name it will use and share that
+  ///   already configured tool.
+  /// - each AnaToolHandle can be declared as a property on the parent
+  ///   tool, allowing to configure the AnaToolHandle that way.  if
+  ///   the user configures the AnaToolHandle that way, it will take
+  ///   precedence over any properties set on the AnaToolHandle.
+  /// - for the future it is foreseen to provide a second property on
+  ///   the parent tool to allow the user picking a particular
+  ///   creation or access pattern, overriding the auto-detected
+  ///   default
 
   template<class T>
   class AnaToolHandle final
@@ -138,21 +480,42 @@ namespace asg
     /// \par Guarantee
     ///   no-fail
   public:
-    AnaToolHandle (AnaToolHandle<T>&& that) noexcept;
+    AnaToolHandle (AnaToolHandle<T>&& that);
+
+
+    /// \brief copy constructor
+    ///
+    /// This will copy the configuration if the argument has not been
+    /// initialized yet, and it will create a shared tool handle if it
+    /// has.
+    ///
+    /// \par Guarantee
+    ///   strong
+    /// \par Failures
+    ///   out of memory II
+  public:
+    AnaToolHandle (const AnaToolHandle<T>& that);
 
 
     /// \brief standard destructor
     /// \par Guarantee
     ///   no-fail
   public:
-    ~AnaToolHandle ();
+    ~AnaToolHandle () noexcept;
 
 
-    /// \brief standard swap
+    /// \brief assignment operator
+    ///
+    /// This will copy the configuration if the argument has not been
+    /// initialized yet, and it will create a shared tool handle if it
+    /// has.
+    ///
     /// \par Guarantee
-    ///   no-fail
+    ///   strong
+    /// \par Failures
+    ///   out of memory II
   public:
-    void swap (AnaToolHandle<T>& that);
+    AnaToolHandle& operator = (const AnaToolHandle<T>& that);
 
 
     /// \brief standard move assignment operator
@@ -162,43 +525,55 @@ namespace asg
     AnaToolHandle<T>& operator = (AnaToolHandle<T>&& that);
 
 
-    /// \brief make a new tool of the type specified in the
-    /// constructor
+    /// \brief standard swap
     /// \par Guarantee
-    ///   strong
-    /// \par Failures
-    ///   tool creation failures\n
-    ///   no tool type specified
-    /// \pre tool has not yet been created
+    ///   no-fail
   public:
-    StatusCode make ();
+    void swap (AnaToolHandle<T>& that) noexcept;
 
-    /// \brief make a new tool of the given type
+
+    /// \brief whether this ToolHandle is completely empty, i.e. it
+    /// has been default constructed and was never assigned any
+    /// content by the user
     ///
-    /// The type name can either be just the type itself or be of the
-    /// form type/name, in which case name indicates the name of the
-    /// tool to be created.
     /// \par Guarantee
     ///   strong
     /// \par Failures
-    ///   tool creation failures
-    /// \pre tool has not yet been created
+    ///   out of memory II
   public:
-    StatusCode make (const std::string& typeName);
+    bool empty () const;
 
-    /// \brief make a new tool of the given type
+    /// \brief whether this is a public tool (or tool handle)
     /// \par Guarantee
-    ///   strong
+    ///   no-fail
+  public:
+    bool isPublic () const noexcept;
+
+    /// \brief whether initialize has been called successfully,
+    ///   i.e. whether the tool is ready to be used
+    /// \par Guarantee
+    ///   no-fail
+  public:
+    bool isInitialized () const noexcept;
+
+
+    /// \brief declare as property on the given tool
+    /// \par Guarantee
+    ///   basic
     /// \par Failures
-    ///   tool creation failures
-    /// \pre tool has not yet been created
-    /// \warn this is only for legacy support and even then should
-    ///   only be called via the \ref ASG_MAKE_ANA_TOOL macro
+    ///   out of memory II\n
+    ///   property declaration failures\n
+    ///   tool already made
   public:
-#ifdef ROOTCORE
-    template<class T2>
-    StatusCode makeNew (std::string val_type);
-#endif
+    template<typename T2> void
+    declarePropertyFor (T2 *tool, const std::string& name,
+			const std::string& description = "");
+
+    /// \brief the tool handle we wrap
+    /// \par Guarantee
+    ///   no-fail
+  public:
+    const ToolHandle<T>& getHandle () const noexcept;
 
 
     /// \brief set the given property of the tool.
@@ -216,125 +591,157 @@ namespace asg
     ///   basic
     /// \par Failures
     ///   property setting failures
-    /// \pre tool has not yet been initialized
+    /// \pre !isInitialized()
   public:
     template <class T2> StatusCode
     setProperty (const std::string& property, const T2& value);
 
-    /// \copydoc setProperty
-  public:
-    template <class T2> StatusCode
-    setProperty (const std::string& property, const ToolHandle<T2>& tool);
 
-    /// \copydoc setProperty
+    /// \brief the type configured for this AnaToolHandle
+    /// \par Guarantee
+    ///   no-fail
   public:
-    template <class T2> StatusCode
-    setProperty (const std::string& property, const AnaToolHandle<T2>& tool);
+    const std::string& type () const noexcept;
 
+    /// \brief set the value of \ref type
+    /// \par Guarantee
+    ///   no-fail
+    /// \pre !isInitialized()
+  public:
+    void setType (std::string val_type) noexcept;
 
-#ifndef ROOTCORE //implementation for cmt releases only so far, I think rootcore releases will already work ~ok
-    /// \copydoc setProperty
+#ifdef ROOTCORE
+    /// \brief set the value of \ref type and a factory based on the
+    /// standard tool constructor
+    ///
+    /// This is mainly for use with RootCore where we occasionally
+    /// have trouble instantiating tools via their dictionaries.  Even
+    /// in that case you shouldn't call this directly, but use the
+    /// \ref ASG_MAKE_ANA_TOOL macro.
+    ///
+    /// \par Guarantee
+    ///   strong
+    /// \par Failures
+    ///   out of memory I
   public:
-    template <class T2> StatusCode
-    setProperty (const std::string& property, const ToolHandleArray<T2>& tool);
+    template<class T2>
+    void setTypeRegisterNew (std::string val_type);
 #endif
 
 
-    /// \brief initialize the tool
+    /// \brief the name configured for this AnaToolHandle
     /// \par Guarantee
-    ///   basic
-    /// \par Failures
-    ///   tool initialization failures
-    /// \pre tool has not yet initialized
+    ///   no-fail
   public:
-    StatusCode initialize ();
+    const std::string& name () const noexcept;
 
-    /// \brief retrieve (i.e. initialize) the tool
+    /// \brief set the value of \ref name
     /// \par Guarantee
-    ///   basic
+    ///   no-fail
+    /// \pre !isInitialized()
+  public:
+    void setName (std::string val_name) noexcept;
+
+    /// \brief the full name of the tool to be used during tool
+    /// initialization
+    /// \par Guarantee
+    ///   strong
     /// \par Failures
-    ///   tool initialization failures
-    /// \pre tool has not yet initialized
+    ///   out of memory II
   public:
-    StatusCode retrieve ();
+    std::string fullName () const;
 
 
-    /// \brief access the tool
+    /// \brief the value of \ref type and \ref name
     /// \par Guarantee
-    ///   no-fail
-    /// \pre isInitialized()
-    /// \post result != nullptr
+    ///   strong
+    /// \par Failures
+    ///   out of memory II
   public:
-    T *operator -> () const noexcept;
+    std::string typeAndName () const;
 
-    /// \brief access the tool
+    /// \brief set the value of \ref type and \ref name
     /// \par Guarantee
-    ///   no-fail
-    /// \pre isInitialized()
+    ///   strong
+    /// \par Failures
+    ///   out of memory II
+    /// \pre !isInitialized()
   public:
-    T& operator * () const noexcept;
+    void setTypeAndName (const std::string& val_typeAndName);
 
-    /// \brief access the tool
+    /// \brief set the value of \ref type and \ref name
     /// \par Guarantee
     ///   no-fail
-    /// \pre isInitialized()
-    /// \post result != nullptr
+    /// \pre !isInitialized()
   public:
-    T *get () const noexcept;
+    void setTypeAndName (std::string val_type, std::string val_name) noexcept;
 
 
-    /// \brief declare as property on the given tool
+    /// \brief initialize the tool
     /// \par Guarantee
     ///   strong
     /// \par Failures
-    ///   out of memory II\n
-    ///   property declaration failures\n
-    ///   tool already made
+    ///   tool initialization failures
+    /// \pre !isInitialized()
   public:
-    template<typename T2> void
-    declarePropertyFor (T2 *tool, const std::string& name,
-			const std::string& description = "");
+    StatusCode initialize ();
 
+    /// \copydoc initialize
+  public:
+    StatusCode retrieve ();
 
-    /// \brief the type configured for this AnaToolHandle
+
+    /// \brief access the tool
     /// \par Guarantee
-    ///   no-fail
+    ///   strong
+    /// \par Failures
+    ///   tool creation failures
+    /// \post result != nullptr
   public:
-#ifdef ROOTCORE
-    const std::string& type () const noexcept;
-#else
-    std::string type () const;
-#endif
+    T *operator -> ();
 
-    /// \brief the name configured for this AnaToolHandle
+    /// \brief access the tool
     /// \par Guarantee
-    ///   no-fail
+    ///   strong
+    /// \par Failures
+    ///   tool creation failures
+    /// \post result != nullptr
   public:
-#ifdef ROOTCORE
-    const std::string& name () const noexcept;
-#else
-    std::string name () const;
-#endif
+    const T *operator -> () const;
 
+    /// \brief access the tool
+    /// \par Guarantee
+    ///   strong
+    /// \par Failures
+    ///   tool creation failures
+  public:
+    T& operator * ();
 
-    /// \brief the tool handle we wrap
+    /// \brief access the tool
     /// \par Guarantee
-    ///   no-fail
+    ///   strong
+    /// \par Failures
+    ///   tool creation failures
   public:
-    const ToolHandle<T>& getHandle () const noexcept;
+    const T& operator * () const;
 
+    /// \brief access the tool
+    /// \par Guarantee
+    ///   strong
+    /// \par Failures
+    ///   tool creation failures
+    /// \post result != nullptr
+  public:
+    T *get ();
 
-    /// \brief the tool handle we can expose to the configuration
-    /// mechanism
-    ///
-    /// This allows to register this AnaToolHandle like a regular
-    /// ToolHandle via declareProperty().  If it is set during
-    /// configuration it will then replace anything provided by
-    /// calling \ref make or \ref setProperty on this AnaToolHandle.
+    /// \brief access the tool
     /// \par Guarantee
-    ///   no-fail
+    ///   strong
+    /// \par Failures
+    ///   tool creation failures
+    /// \post result != nullptr
   public:
-    ToolHandle<T>& handle ();
+    const T *get () const;
 
 
     /// \brief whether this tool handle has been configured by the
@@ -349,47 +756,113 @@ namespace asg
     bool isUserConfigured () const noexcept;
 
 
-    /// \brief whether the tool can be configured by us
+    /// \brief the \ref detail::AnaToolHandleMode for this handle
+    ///
+    /// This is mostly meant for internal use by the setProperty
+    /// method, not for use by the end-user
     ///
-    /// if this refers to a shared tool or has been configured via the
-    /// ToolHandle, then we can't configure the tool ourselves.  we
-    /// can still call the setProperty methods, they just won't do
-    /// anything.
     /// \par Guarantee
-    ///   no-fail
+    ///   strong
+    /// \par Failures
+    ///   out of memory II
   public:
-    bool isConfigurable () const;
+    detail::AnaToolHandleMode mode () const;
 
 
-    /// \brief whether initialize has been called successfully,
-    ///   i.e. whether the tool is ready to be used
+    /// \brief the \ref detail::AnaToolConfig for this handle
+    ///
+    /// This is mostly meant for internal use by the setProperty
+    /// method, not for use by the end-user
+    ///
     /// \par Guarantee
-    ///   no-fail
+    ///   strong
+    /// \par Failures
+    ///   out of memory II
   public:
-    bool isInitialized () const noexcept;
+    const detail::AnaToolConfig& config () const;
 
 
-    /// \brief whether we are in the state before calling make
+    /// \brief whether the user is allowed to configure this with an
+    /// empty tool handle
+    ///
+    /// This normally defaults to whether the developer initialized
+    /// this to a valid ToolHandle to begin with, but depending on the
+    /// situation it can be overridden.
     ///
-    /// Normally users don't need to check this, but sometimes this
-    /// can be worthwhile to check for debugging purposes.
     /// \par Guarantee
     ///   no-fail
   public:
-    bool inPremakeState () const noexcept;
+    bool allowEmpty () const noexcept;
+
+
 
+    /// \brief set the value of \ref allowEmpty
+    /// \par Guarantee
+    ///   no-fail
+    /// \pre !isInitialized()
+  public:
+    void setAllowEmpty (bool val_allowEmpty = true) noexcept;
+
+
+
+    //
+    // deprecated interface
+    //
 
-    /// \brief whether we are in a broken state
+    /// \brief whether the tool can be configured by us, i.e. whether
+    /// properties set via \ref setProperty will be used for something
+    ///
+    /// For the most part this is the reverse of \ref isUserConfigured
+    /// except some shared tools may register as not user configured
+    /// and not configurable either.  if the properties set are used
+    /// to generate debugging output even a user configured tool may
+    /// register as configurable.
     ///
-    /// Normally users don't need to check this, but sometimes this
-    /// can be worthwhile to check for debugging purposes.  Normally
-    /// tools get into a broken state either because one of the
-    /// configuration functions failed, or because the content of this
-    /// object was moved to another tool handle.
     /// \par Guarantee
     ///   no-fail
+    /// \warn this may go away at some point as we may be using the
+    /// properties for more and more things (e.g. info printouts)
+  public:
+    bool isConfigurable () const;
+
+  public:
+    ASG_DEPRECATED ("please use isInitialized() instead")
+    bool inPremakeState () const noexcept {
+      return !isInitialized();}
+
+  public:
+    ASG_DEPRECATED ("please use isInitialized() instead")
+    bool inBrokenState () const noexcept {
+      return false;};
+
+  public:
+    ASG_DEPRECATED ("no longer need to call make()")
+    StatusCode make () {
+      return StatusCode::SUCCESS;};
+
+  public:
+    ASG_DEPRECATED ("please use setType() or setTypeAndName() instead")
+    StatusCode make (std::string val_type) noexcept {
+      if (!val_type.empty()) {
+	if (val_type.find ('/') != std::string::npos)
+	  setTypeAndName (val_type);
+	else
+	  setType (val_type); }
+      return StatusCode::SUCCESS; };
+
   public:
-    bool inBrokenState () const noexcept;
+    ASG_DEPRECATED ("please use either getHandle() or declarePropertyFor() instead")
+    ToolHandle<T>& handle () {
+      return *m_handleUser;};
+
+#ifdef ROOTCORE
+  public:
+    template<class T2>
+    ASG_DEPRECATED ("please use setTypeRegisterNew() instead")
+    StatusCode makeNew (std::string val_type) {
+      setTypeRegisterNew<T2> (std::move (val_type));
+      return StatusCode::SUCCESS;}
+#endif
 
 
 
@@ -397,64 +870,42 @@ namespace asg
     // private interface
     //
 
-    /// \brief the different states of the tool handle
+    /// \brief any stuff we need to release as part of cleanup
+    ///
+    /// This is protected by \ref m_isInitialized and should not be
+    /// accessed until \ref m_isInitialized is true.
   private:
-    enum class State
-    {
-      /// \brief the beginning state
-      BEGIN,
-
-      /// \brief we are using a pre-initialized tool, i.e. we ignore
-      /// all setProperty() requests and initialize() essentially just
-      /// unlocks it
-      PREINITIALIZED,
-
-      /// \brief the tool has been made, but not initialized
-      CREATED,
+    detail::AnaToolCleanup m_cleanup;
 
-      /// \brief the tool has been initialized and can be used
-      INITIALIZED,
+    /// \brief the configuration for this tool
+  private:
+    detail::AnaToolConfig m_config;
 
-      /// \brief we encountered an error in setProperty
-      ///
-      /// This is to emulate the Athena behavior in RootCore,
-      /// i.e. that setProperty failures only show up when actually
-      /// initializing the tool, not when setting properties on it.
-      BAD_PROPERTY,
+    /// \brief the value of \ref name
+  private:
+    std::string m_name;
 
-      /// \brief an error has occurred in the tool creation process
-      BROKEN
-    };
+    /// \brief the name of the parent
+  private:
+    std::string m_parentName;
 
-    /// \brief the current \ref State of the tool handle
+    /// \brief the pointer to the parent
   private:
-    State m_state = State::BEGIN;
+    parentType_t *m_parentPtr = nullptr;
 
 
-    /// \brief the \ref ToolHandle we wrap our tool handle around
+    /// \brief the \ref ToolHandle exposed to the user
     ///
-    /// This serves as a backend for a lot of our functions, and we
-    /// rely on its properties as much as possible instead of trying
-    /// to implement our own.  As such we purposely limit write access
-    /// by the user to this handle.  It can be declared as a property
-    /// on the parent tool and set during the configuration stage, but
-    /// otherwise it is off-limits to the user.
+    /// This primarily serves to allow the user to set this like a
+    /// regular ToolHandle property.  During initialize it is then
+    /// updated to refer to the actually used tool.
     ///
     /// This is done as a shared pointer, so that the include
     /// dependency is only pulled in for the source file that actually
     /// uses the AnaToolHandle.  That in turn reduces the number of
     /// public dependencies an Athena package has to expose.
   private:
-    std::shared_ptr<ToolHandle<T>> m_handle;
-
-
-    /// \brief the parent of the tool
-    ///
-    /// in RootCore we can not ask the ToolHandle for the pointer to
-    /// the parent, so instead we cache it here and just check in
-    /// Athena that it is the same as in the ToolHandle
-  private:
-    parentType_t *m_parent = nullptr;
+    std::shared_ptr<ToolHandle<T>> m_handleUser;
 
     /// \brief the typeAndName at time of creation
     ///
@@ -463,152 +914,88 @@ namespace asg
   private:
     std::string m_originalTypeAndName;
 
+    /// \brief the value of \ref isInitialized
+  private:
+    std::atomic<bool> m_isInitialized {false};
+
     /// \brief the pointer to the tool we use
     ///
     /// This is used for actually accessing the tool, independent of
-    /// how we created it.
+    /// who created it or how.  Mostly this is a performance
+    /// optimization to avoid going back to the ToolHandle every
+    /// single time.
+    ///
+    /// This is protected by \ref m_isInitialized and should not be
+    /// accessed until \ref m_isInitialized is true.
   private:
     T *m_toolPtr = nullptr;
 
-    /// \brief the value of \ref isUserConfigured cached when we make
-    /// the tool
-  private:
-    bool m_isUserConfigured = false;
-
-
-    /// \brief do all the checks that need to be done before running
-    /// any version of make
-    /// \par Guarantee
-    ///   basic
-    /// \par Failures
-    ///   tool creation failures\n
-    ///   pre-condition failures
-  private:
-    StatusCode
-    preMake (const std::string& val_type);
-
-    /// \brief actually make the tool, if we make our own
-    /// \par Guarantee
-    ///   basic
-    /// \par Failures
-    ///   tool creation failures\n
-    ///   pre-condition failures
-  private:
-    StatusCode
-    doMake ();
-
-
-    /// \brief do all the checks that need to be done before running
-    /// any version of setProperty
-    /// \par Guarantee
-    ///   basic
-    /// \par Failures
-    ///   tool creation failures\n
-    ///   pre-condition failures
-  private:
-    StatusCode preSetProperty (const std::string& property);
-
-
-
-    //
-    // private interface for RootCore
-    //
-
-#ifdef ROOTCORE
-    /// \brief the pointer to the tool used for configuration
-  private:
-    asg::AsgTool *m_toolConfig = nullptr;
-
-    /// \brief the smart pointer to the tool, if we created it
-    /// ourselves
+    /// \brief the value of \ref getMode cached when we initialize the
+    /// tool
     ///
-    /// If we create the tool ourselves, we are responsible for
-    /// cleaning it up.  Originally this was a unique_ptr, but I
-    /// changed it to a shared pointer, so that it users don't have to
-    /// include all the possible tool classes in their code.  Also,
-    /// this allows to share a tool between multiple \ref
-    /// AnaToolHandle objects.
+    /// This is protected by \ref m_isInitialized and should not be
+    /// accessed until \ref m_isInitialized is true.
   private:
-    std::shared_ptr<T> m_toolOwn;
+    detail::AnaToolHandleMode m_mode = detail::AnaToolHandleMode::EMPTY;
 
-    /// \brief the weak pointer referencing shared tools
+    /// \brief get the mode with which this ToolHandle will be initialized
+    ///
+    /// This exists in two modes, one passing back a shared tool
+    /// pointer and one without it.  as a rule of thumb, the version
+    /// passing back the shared tool should be used by initialize,
+    /// whereas all the places just wanting to check that will happen
+    /// can/should call the version without.
+    ///
     /// \par Guarantee
     ///   strong
     /// \par Failures
     ///   out of memory II
-    /// \brief !m_name.empty()
   private:
-    std::weak_ptr<T>& sharedToolPointer () const;
-#endif
-
-
+    detail::AnaToolHandleMode
+    getMode (std::shared_ptr<detail::AnaToolShare>& sharedTool) const;
 
-    //
-    // private interface for Athena
-    //
-
-#ifndef ROOTCORE
+    /// \copydoc getMode
   private:
-    std::vector<std::string> m_addedProperties;
+    detail::AnaToolHandleMode
+    getMode () const;
 
-    // \brief this contains a release function we use, so that we can
-    // break down on include dependencies
-  private:
-    std::function<void (ToolHandle<T> *)> m_releaseFunction;
 
+    /// \brief the value of \ref allowEmpty
   private:
-    std::string fullName () const;
-#endif
-
-
-
-    //
-    // legacy interface
-    //
-
-    // prevent copying
-    AnaToolHandle (const AnaToolHandle<T>&) = delete;
-    AnaToolHandle<T>& operator = (const AnaToolHandle<T>&) = delete;
+    bool m_allowEmpty = false;
 
 
-    /// \brief whether this ToolHandle is completely empty
+    /// \brief make a tool by retrieving the ToolHandle
     /// \par Guarantee
-    ///   no-fail
-  public:
-    bool empty() const noexcept;
-
-
-  private:
-    void setType (std::string val_type) {
-      setTypeAndName (std::move (val_type), name());}
-
+    ///   strong
+    /// \par Failures
+    ///   tool creation failures
   private:
-    void setName (std::string val_name) {
-      setTypeAndName (type(), std::move (val_name));}
+    StatusCode makeToolRetrieve
+      (T*& toolPtr, ToolHandle<T>& toolHandle) const;
 
-  private:
-    void setTypeAndName (std::string val_type,
-			 std::string val_name) {
-      if (val_type.empty())
-	m_handle->setTypeAndName (std::move (val_type));
-      else if (val_name.empty())
-	m_handle->setTypeAndName (std::move (val_name));
-      else
-	m_handle->setTypeAndName (val_type + "/" + val_name);}
 
+    /// \brief a mutex to ensure that we don't call initialize twice
+    /// concurrently
+    ///
+    /// This is a recursive mutex so that we can lock both in \ref
+    /// initialize and \ref get without conflict.
   private:
-    void setTypeAndName (std::string val_typeAndName) {
-      m_handle->setTypeAndName (std::move (val_typeAndName));}
+    std::recursive_mutex m_initializeMutex;
   };
 }
 
 /// \brief create the tool in the given tool handle
-#ifdef ROOTCORE
 #define ASG_MAKE_ANA_TOOL(handle,type)	\
-  (handle).template makeNew<type> (#type)
+  (ASG_SET_ANA_TOOL_TYPE(handle,type), StatusCode (StatusCode::SUCCESS))
+
+/// \brief set the tool type on the tool handle, using new in rootcore
+#ifdef ROOTCORE
+#define ASG_SET_ANA_TOOL_TYPE(handle,type)	\
+  (handle).template setTypeRegisterNew<type> (#type)
 #else
-#define ASG_MAKE_ANA_TOOL(handle,type)	\
-  (handle).make (#type)
+#define ASG_SET_ANA_TOOL_TYPE(handle,type)	\
+  (handle).setType (#type)
 #endif
 
 #include <AsgTools/AnaToolHandle.icc>
diff --git a/Control/AthToolSupport/AsgTools/AsgTools/AnaToolHandle.icc b/Control/AthToolSupport/AsgTools/AsgTools/AnaToolHandle.icc
index 82ea4c2d14d4c31df7f0ea337658813bc0aead65..6166713f0ee9ddafea33408e544a8996cd6d7aad 100644
--- a/Control/AthToolSupport/AsgTools/AsgTools/AnaToolHandle.icc
+++ b/Control/AthToolSupport/AsgTools/AsgTools/AnaToolHandle.icc
@@ -23,481 +23,770 @@ namespace asg
     StatusCode toolExists( const std::string& fullName, interfaceType_t*& tool );
     // StatusCode factoryExists( const std::string& type );
 #endif
-  }
-
-
-
-  template <typename T>
-  std::ostream& operator << (std::ostream& str, const AnaToolHandle<T>& obj)
-  {
-    return str << obj.getHandle();
-  }
 
 
 
-  template<class T> void AnaToolHandle<T> ::
-  testInvariant () const
-  {
-#define CHECK_INVARIANT(x)			\
-    if (!(x)) { std::cerr << __FILE__ << ":" << __LINE__ << ": invariant violated: " << #x << std::endl; std::abort(); }
+    /// \brief do a checked cast from one ToolHandle interface to
+    /// another
+    /// \par Guarantee
+    ///   basic
+    /// \par Failures
+    ///   interface not supported for tool
+    template<typename T1,typename T2> StatusCode
+    toolHandleCast (ToolHandle<T1>& to, ToolHandle<T2>& from)
+    {
+      using namespace msgUserCode;
 
-    // General requirements
-    CHECK_INVARIANT (&*this != nullptr);
-    CHECK_INVARIANT (m_handle != nullptr);
 #ifdef ROOTCORE
-    CHECK_INVARIANT (m_toolOwn == nullptr || m_toolOwn.get() == m_toolPtr);
+      to = ToolHandle<T1> (dynamic_cast<T1*>(&*from));
+      if (!from.empty() && &*to == nullptr)
+      {
+	ANA_MSG_ERROR ("failed to cast from type " << typeid(T2).name() << " to  " << typeid(T1).name());
+	return StatusCode::FAILURE;
+      }
 #else
-    CHECK_INVARIANT (m_parent == m_handle->parent());
-    CHECK_INVARIANT (m_releaseFunction);
+      to = ToolHandle<T1> (from.typeAndName(), from.parent());
+      if (!from.empty())
+        ANA_CHECK (to.retrieve());
 #endif
+      return StatusCode::SUCCESS;
+    }
+
+
+
 
-    // State-dependent requirements
-    switch (m_state)
+
+    /// \brief the information needed to share a tool
+
+    class AnaToolShare
     {
-    case State::BEGIN:
-      break;
-    case State::PREINITIALIZED:
-      CHECK_INVARIANT (m_toolPtr != nullptr);
-      CHECK_INVARIANT (m_isUserConfigured == true);
-      break;
-    case State::CREATED:
-#ifdef ROOTCORE
-      CHECK_INVARIANT (m_toolPtr != nullptr);
-      CHECK_INVARIANT (m_toolConfig != nullptr);
-#endif
-      CHECK_INVARIANT (m_isUserConfigured == false);
-      break;
-    case State::INITIALIZED:
-      CHECK_INVARIANT (m_toolPtr != nullptr);
-      break;
-    case State::BAD_PROPERTY:
-      CHECK_INVARIANT (m_toolPtr != nullptr);
-      break;
-    case State::BROKEN:
-      break;
-    }
+      //
+      // public interface
+      //
 
-#undef CHECK_INVARIANT
-  }
+      /// \brief standard constructor
+      /// \par Guarantee
+      ///   strong
+      /// \par Failures
+      ///   out of memory II
+    public:
+      AnaToolShare (const ToolHandle<interfaceType_t>& val_th,
+		    AnaToolCleanup val_cleanup);
+
+
+      /// \brief the tool we contain
+      /// \par Guarantee
+      ///   no-fail
+      /// \post result != nullptr
+    public:
+      ToolHandle<interfaceType_t>& th ();
+
+
+
+      //
+      // private interface
+      //
+
+      /// \brief the value of \ref tool
+    private:
+      ToolHandle<interfaceType_t> m_th;
+
+      /// \brief resources to release shen we are releasing the tool
+    private:
+      AnaToolCleanup m_cleanup;
+    };
+
+
+
+
+
+    /// \brief a service for sharing tools of a given type
+
+    class AnaToolShareList
+    {
+      //
+      // public interface
+      //
+
+      /// \brief the singleton we are using
+      /// \par Guarantee
+      ///   no-fail
+    public:
+      static AnaToolShareList& singleton () noexcept;
+
+
+      /// \brief get the share for the given name, or nullptr if no
+      /// share has been defined
+      /// \par Guarantee
+      ///   strong
+      /// \par Failures
+      ///   out of memory I
+    public:
+      std::shared_ptr<AnaToolShare>
+      getShare (const std::string& name) const;
+
+
+      /// \brief set the share for the given name
+      /// \return the share to use, this is either the share passed in
+      /// or the already set share
+      /// \par Guarantee
+      ///   strong
+      /// \par Failures
+      ///   out of memory II
+    private:
+      std::shared_ptr<AnaToolShare>
+      setShare (const std::string& name,
+		std::unique_ptr<AnaToolShare> val_share);
+
+
+      /// \brief make or get a share for the given name
+      /// \return the share to use, either freshly created or
+      /// retrieved from the store
+      /// \par Guarantee
+      ///   strong
+      /// \par Failures
+      ///   tool creation failures\n
+      ///   out of memory II
+    public:
+      StatusCode
+      makeShare (const std::string& name,
+		 const AnaToolConfig& config,
+		 std::shared_ptr<AnaToolShare>& result);
+
+
+
+      //
+      // private interface
+      //
+
+      /// \brief the shares we manage
+    private:
+      std::map<std::string,std::weak_ptr<AnaToolShare> > m_shared;
+    };
 
 
 
-  template<class T> AnaToolHandle<T> ::
-  AnaToolHandle (const std::string& val_name, parentType_t *val_parent)
-    : m_handle (new ToolHandle<T> (val_name, val_parent)),
-      m_parent (val_parent),
-      m_originalTypeAndName (m_handle->typeAndName ())
 #ifndef ROOTCORE
-    , m_releaseFunction ([] (ToolHandle<T> *m_handle) {
-	using namespace msgToolHandle;
-	//tool has 2 ref counts out of the box?? (ToolSvc and, and ToolSvc again because of the queryInterface call (line 348 of ToolSvc.cpp .. and see line 34 of AlgTool.cpp))
-	if(m_handle->isSet()) {
-	  //before deleting, check ToolSvc still knows about it, because it might already have been destroyed by ToolSvc finalize
-	  interfaceType_t *tool = nullptr;
-          if( !detail::toolExists( m_handle->parentName() + "." + m_handle->name(), tool ) ) return; //already deleted
-	  ANA_MSG_DEBUG( *m_handle << " " << (*m_handle)->refCount() );
-	  //if((*m_handle)->refCount()==3) (*m_handle)->release(); //may cause problem if the other 'something' wants to use the tool still??
-	  //ANA_MSG_DEBUG (*m_handle << " " << (*m_handle)->refCount());
-	  if((*m_handle)->refCount()==2) (*m_handle)->release(); //may cause problem if the other 'something' wants to use the tool still??
-	  ANA_MSG_DEBUG (*m_handle << " " << (*m_handle)->refCount());
-	  m_handle->release().ignore(); //triggers tool destruction
-	}
-      })
-#endif
-  {
-#ifndef NDEBUG
-    this->testInvariant ();
+    /// \brief manage a single property in the job options service
+
+    struct PropertyValueManager
+    {
+      PropertyValueManager (const std::string& val_toolName,
+			    const std::string& val_name)
+	: m_toolName (val_toolName), m_name (val_name)
+      {
+      }
+
+      ~PropertyValueManager ()
+      {
+	if (m_cleanup)
+	  detail::removePropertyFromCatalogue (m_toolName, m_name).ignore();
+      }
+
+      std::string m_toolName;
+      std::string m_name;
+      bool m_cleanup = false;
+    };
+
+
+
+    /// \brief a \ref AnaToolProperty containing a regular value for
+    /// Athena
+
+    class AnaToolPropertyValueAthena : public AnaToolProperty
+    {
+    public:
+      template<typename Type>
+      AnaToolPropertyValueAthena (const Type& val_value)
+	: m_value (Gaudi::Utils::toString (val_value))
+      {
+      }
+
+    public:
+      virtual StatusCode
+      applyPropertyAthena (const std::string& toolName,
+			   const std::string& name,
+			   AnaToolCleanup& cleanup)
+	const override;
+
+    private:
+      std::string m_value;
+    };
 #endif
-  }
 
 
 
-  template<class T> AnaToolHandle<T> ::
-  AnaToolHandle (AnaToolHandle<T>&& that) noexcept
-    : m_state (that.m_state),
-      m_handle (that.m_handle),
-      m_parent (that.m_parent),
-      m_originalTypeAndName (std::move (that.m_originalTypeAndName)),
-      m_toolPtr (that.m_toolPtr),
-      m_isUserConfigured (that.m_isUserConfigured),
+
+
 #ifdef ROOTCORE
-      m_toolConfig (that.m_toolConfig),
-      m_toolOwn (std::move (that.m_toolOwn))
-#else
-      m_addedProperties (std::move (that.m_addedProperties)),
-      m_releaseFunction (that.m_releaseFunction)
-#endif
-  {
-    that.m_state = State::BROKEN;
+    /// \brief a \ref AnaToolProperty containing a regular value in
+    /// RootCore
 
-#ifndef NDEBUG
-    that.testInvariant ();
-    testInvariant ();
+    template<typename Type>
+    class AnaToolPropertyValueRootCore : public AnaToolProperty
+    {
+    public:
+      AnaToolPropertyValueRootCore (const Type& val_value)
+	: m_value (val_value)
+      {}
+
+    public:
+      virtual StatusCode
+      applyPropertyRootCore (AsgTool& tool, const std::string& name,
+			     AnaToolCleanup& /*cleanup*/)
+	const override
+      {
+	using namespace msgToolHandle;
+	ANA_CHECK (tool.setProperty (name, m_value));
+	return StatusCode::SUCCESS;
+      }
+
+    private:
+      Type m_value;
+    };
 #endif
-  }
 
 
 
-  template<class T> void AnaToolHandle<T> ::
-  swap (AnaToolHandle<T>& that)
-  {
-#ifndef NDEBUG
-    testInvariant ();
-    that.testInvariant ();
-#endif
 
-    std::swap (m_state, that.m_state);
-    m_handle.swap (that.m_handle);
-    std::swap (m_parent, that.m_parent);
-    m_originalTypeAndName.swap (that.m_originalTypeAndName);
-    std::swap (m_toolPtr, that.m_toolPtr);
-    std::swap (m_isUserConfigured, that.m_isUserConfigured);
+
+    /// \brief a \ref AnaToolProperty containing an \ref AnaToolConfig
+    /// for configuring a private sub-tool
+
+    template<typename Type>
+    class AnaToolPropertyPrivateTool : public AnaToolProperty
+    {
+    public:
+      AnaToolPropertyPrivateTool (const AnaToolConfig& val_config)
+	: m_config (val_config)
+      {}
+
 #ifdef ROOTCORE
-    std::swap (m_toolConfig, that.m_toolConfig);
-    m_toolOwn.swap (that.m_toolOwn);
-#else
-    m_addedProperties.swap (that.m_addedProperties);
-    m_releaseFunction.swap (that.m_releaseFunction);
+    public:
+      virtual StatusCode
+      applyPropertyRootCore (AsgTool& tool, const std::string& name,
+			     AnaToolCleanup& cleanup)
+	const override
+      {
+	using namespace msgToolHandle;
+	ToolHandle<Type> th;
+	AnaToolCleanup mycleanup;
+	ANA_CHECK (m_config.makeTool (name, &tool, th, mycleanup));
+	cleanup.addCleanup (std::move (mycleanup));
+	ANA_CHECK (tool.setProperty (name, th));
+	return StatusCode::SUCCESS;
+      }
 #endif
 
-#ifndef NDEBUG
-    testInvariant ();
-    that.testInvariant ();
+#ifndef ROOTCORE
+    private:
+      virtual StatusCode
+      applyPropertyAthena (const std::string& toolName,
+			   const std::string& name,
+			   AnaToolCleanup& cleanup)
+	const override
+      {
+	using namespace msgToolHandle;
+	ANA_CHECK (m_config.applyPropertiesAthena (toolName + "." + name, cleanup));
+
+	// this is so we clear out properties from catalogue when tool
+	// is destroyed.  DISABLED: as we no longer release tools in Athena
+	// std::shared_ptr<PropertyValueManager> manager
+	//   (new PropertyValueManager (th.name(), name));
+	// cleanup.addCleanup (manager);
+
+	// for athena we hand our property to the joboptions svc
+        ANA_CHECK (detail::addPropertyToCatalogue (toolName, name, m_config.type() + "/" + name));
+	// manager->m_cleanup = true;
+	return StatusCode::SUCCESS;
+      }
 #endif
-  }
-
 
+    private:
+      AnaToolConfig m_config;
+    };
 
-  template<class T> AnaToolHandle<T>& AnaToolHandle<T> ::
-  operator = (AnaToolHandle<T>&& that)
-  {
-    // no invariant used
-    swap (that);
-    return *this;
-  }
 
 
 
-  template<class T> AnaToolHandle<T> ::
-  ~AnaToolHandle ()
-  {
-    using namespace msgToolHandle;
-#ifndef NDEBUG
-    this->testInvariant ();
-#endif
 
 #ifndef ROOTCORE
+    /// \brief a \ref AnaToolProperty copying a tool configuration
+    /// from the job options service to a new place
+
+    class AnaToolPropertyCopyTool : public AnaToolProperty
+    {
+    public:
+      AnaToolPropertyCopyTool (const std::string& val_type,
+                               const std::string& val_name);
 
-    // if we caused properties to be set in the catalogue, we must
-    // cleanup too
-    for (auto& prop : m_addedProperties)
-      detail::removePropertyFromCatalogue( fullName() , prop ).ignore();
+    private:
+      virtual StatusCode
+      applyPropertyAthena (const std::string& toolName,
+			   const std::string& name,
+			   AnaToolCleanup& cleanup)
+	const override;
 
-    if (m_releaseFunction)
-      m_releaseFunction (m_handle.get());
+      /// \brief the type of the tool to create
+    private:
+      std::string m_type;
 
+      /// \brief the name of the source tool
+    private:
+      std::string m_name;
+    };
 #endif
-  }
 
 
-  template<class T> bool
-  AnaToolHandle<T> ::
-  empty () const noexcept
-  {
-    //handle is empty if: it wasn't user configured and our type and name are not set, or it is user configured and the member handle is empty
-    return( (  isUserConfigured() && ( m_handle->empty() || m_handle->typeAndName()=="PublicToolHandle('')" || m_handle->typeAndName()=="PrivateToolHandle('')" ) )
-	    || ( (!isUserConfigured() && type()=="" && name()=="") ) );
-  }
 
 
 
+    /// \brief a \ref AnaToolProperty containing an \ref AnaToolConfig
+    /// for configuring a public sub-tool
+
+    template<typename Type>
+    class AnaToolPropertyPublicTool : public AnaToolProperty
+    {
+    public:
+      AnaToolPropertyPublicTool (const std::string& val_name,
+				 const AnaToolConfig& val_config)
+	: m_name (val_name), m_config (val_config)
+      {}
+
 #ifdef ROOTCORE
-   template<class T> inline const std::string&
-   AnaToolHandle<T> ::
-   type () const noexcept
-   {
-#ifndef NDEBUG
-     this->testInvariant ();
+    public:
+      virtual StatusCode
+      applyPropertyRootCore (AsgTool& tool, const std::string& name,
+			     AnaToolCleanup& cleanup)
+	const override
+      {
+	using namespace msgToolHandle;
+	std::shared_ptr<AnaToolShare> share;
+	ANA_CHECK (AnaToolShareList::singleton().makeShare
+		     (m_name, m_config, share));
+	cleanup.addCleanup (share);
+	ToolHandle<Type> myth;
+	ANA_CHECK (toolHandleCast (myth, share->th()));
+	ANA_CHECK (tool.setProperty (name, myth));
+	return StatusCode::SUCCESS;
+      }
 #endif
-     return m_handle->type();
-   }
 
-   template<class T> inline const std::string&
-   AnaToolHandle<T> ::
-   name () const noexcept
-   {
-#ifndef NDEBUG
-     this->testInvariant ();
-#endif
-     return m_handle->name();
-   }
-#else
-   template<class T> inline std::string
-   AnaToolHandle<T> ::
-   type () const
-   {
-#ifndef NDEBUG
-     this->testInvariant ();
+#ifndef ROOTCORE
+    private:
+      virtual StatusCode
+      applyPropertyAthena (const std::string& toolName,
+			   const std::string& name,
+			   AnaToolCleanup& cleanup)
+	const override
+      {
+	using namespace msgToolHandle;
+	std::shared_ptr<AnaToolShare> share;
+	ANA_CHECK (AnaToolShareList::singleton().makeShare
+		     (m_name, m_config, share));
+	cleanup.addCleanup (share);
+
+	ToolHandle<Type> th;
+	ANA_CHECK (toolHandleCast (th, share->th()));
+
+	// this is so we clear out properties from catalogue when tool
+	// is destroyed.  DISABLED: we no longer clear out tools after
+	// we are done with them
+	// std::shared_ptr<PropertyValueManager> manager
+	//   (new PropertyValueManager (th.name(), name));
+	// cleanup.addCleanup (manager);
+
+	// for athena we hand our property to the joboptions svc
+	ANA_CHECK (detail::addPropertyToCatalogue (toolName, name, th.typeAndName()));
+        // manager->m_cleanup = true;
+	return StatusCode::SUCCESS;
+      }
 #endif
-     return m_handle->type();
-   }
 
-   template<class T> inline std::string
-   AnaToolHandle<T> ::
-   name () const
-   {
-#ifndef NDEBUG
-     this->testInvariant ();
-#endif
-     return m_handle->name();
-   }
-#endif
+    private:
+      std::string m_name;
+      AnaToolConfig m_config;
+    };
+
 
 
 
-  template<class T> StatusCode
-  AnaToolHandle<T> ::
-  make (const std::string& val_type)
-  {
-    using namespace msgToolHandle;
-#ifndef NDEBUG
-    this->testInvariant ();
-#endif
 
-    ANA_CHECK (preMake (val_type));
-    if (m_state != State::BEGIN)
+#ifdef ROOTCORE
+    template<typename Type> void AnaToolConfig ::
+    registerNew ()
     {
-#ifndef NDEBUG
-      this->testInvariant ();
+      m_factory = [] (AsgTool*& tool, const std::string& name) -> StatusCode {
+	tool = new Type (name); return StatusCode::SUCCESS;};
+    }
 #endif
+
+
+
+#ifdef ROOTCORE
+    template<typename Type> StatusCode AnaToolConfig ::
+    setProperty (const std::string& val_name, const Type& val_value)
+    {
+      std::shared_ptr<detail::AnaToolProperty> anaProperty
+	(new detail::AnaToolPropertyValueRootCore<Type> (val_value));
+      addProperty (val_name, anaProperty);
       return StatusCode::SUCCESS;
     }
-    return doMake ();
-  }
+#else
+    template<typename Type> StatusCode AnaToolConfig ::
+    setProperty (const std::string& val_name, const Type& val_value)
+    {
+      using namespace msgToolHandle;
+      std::shared_ptr<detail::AnaToolProperty> anaProperty
+	(new detail::AnaToolPropertyValueAthena (val_value));
+      addProperty (val_name, anaProperty);
+      return StatusCode::SUCCESS;
+    }
+#endif
 
 
 
-  template <class T>
-  StatusCode AnaToolHandle<T> ::
-  make ()
-  {
-    using namespace msgToolHandle;
-#ifndef NDEBUG
-    this->testInvariant ();
+    template<typename Type> StatusCode AnaToolConfig ::
+    setProperty (const std::string& val_name,
+		 const AnaToolHandle<Type>& val_value)
+    {
+      using namespace msgToolHandle;
+
+      // once initialized the AnaToolHandle is not that different from
+      // a regular ToolHandle and we just use it as such
+      if (val_value.isInitialized())
+	return setProperty (val_name, val_value.getHandle());
+
+      switch (val_value.mode())
+      {
+      case AnaToolHandleMode::EMPTY:
+	return setProperty (val_name, ToolHandle<Type> ());
+      case AnaToolHandleMode::CREATE_PRIVATE:
+	{
+	  std::shared_ptr<AnaToolPropertyPrivateTool<Type> > anaProperty
+	    (new AnaToolPropertyPrivateTool<Type> (val_value.config()));
+	  addProperty (val_name, anaProperty);
+	}
+	return StatusCode::SUCCESS;
+      case AnaToolHandleMode::CREATE_SHARED:
+      case AnaToolHandleMode::RETRIEVE_SHARED:
+	{
+	  std::shared_ptr<AnaToolPropertyPublicTool<Type> > anaProperty
+	    (new AnaToolPropertyPublicTool<Type> (val_value.name(), val_value.config()));
+	  addProperty (val_name, anaProperty);
+	}
+	return StatusCode::SUCCESS;
+      case AnaToolHandleMode::USER:
+	return setProperty (val_name, val_value.getHandle());
+      }
+      return StatusCode::FAILURE; //compiler dummy
+    }
+
+
+
+#ifndef ROOTCORE
+    template<typename Type> StatusCode AnaToolConfig ::
+    setProperty (const std::string& val_name,
+		 const ToolHandle<Type>& val_value)
+    {
+      using namespace msgToolHandle;
+
+      //strip the parent name
+      if (val_value.empty())
+        return setProperty (val_name, std::string ());
+      else if (val_value.isPublic())
+      {
+        return setProperty (val_name,
+                            val_value.type() + "/" + val_value.name());
+      } else
+      {
+        std::shared_ptr<AnaToolPropertyCopyTool> shared
+          (new AnaToolPropertyCopyTool
+           (val_value.type(), val_value.parentName() + "." + val_value.name()));
+        addProperty (val_name, shared);
+        return StatusCode::SUCCESS;
+      }
+    }
+
+
+
+    template<typename Type> StatusCode AnaToolConfig ::
+    setProperty (const std::string& val_name,
+		 const ToolHandleArray<Type>& val_value)
+    {
+      using namespace msgToolHandle;
+
+      std::vector<std::string> tools;
+      // loop over toolhandles in array, strip off any parent naming
+      // and set property with the result
+      for (auto& toolHandle : val_value)
+      {
+	if (toolHandle.empty())
+	{
+	  ANA_MSG_ERROR ("trying to initialize ToolHandleArray property " << val_name << " with empty handle");
+	  return StatusCode::FAILURE;
+	}
+      
+	//strip the parent name
+	std::string tool_name = toolHandle.name();
+	tools.push_back (toolHandle.type() + "/" + tool_name);
+      }
+
+      return setProperty (val_name, tools);
+    }
 #endif
 
-    ANA_CHECK (preMake (""));
-    if (m_state != State::BEGIN)
+
+
+
+    template<typename ToolType> StatusCode AnaToolConfig ::
+    makeTool (const std::string& name,
+              parentType_t *parent,
+	      ToolHandle<ToolType>& th,
+	      AnaToolCleanup& cleanup) const
     {
-#ifndef NDEBUG
-      this->testInvariant ();
+      using namespace msgUserCode;
+      ToolHandle<interfaceType_t> baseTH;
+      AnaToolCleanup baseCleanup;
+      ANA_CHECK (makeBaseTool (name, parent, baseTH, baseCleanup));
+      ANA_CHECK (toolHandleCast (th, baseTH));
+      cleanup.swap (baseCleanup);
+#ifndef ROOTCORE
+      baseTH->release ();
 #endif
       return StatusCode::SUCCESS;
     }
-    if (type().empty())
-    {
-      ANA_MSG_ERROR ("called AnaToolHandle::make() without a type");
-      ANA_MSG_ERROR ("you can either pass it into make() directly,");
-      ANA_MSG_ERROR ("or as part of the name to the constructor");
-      ANA_MSG_ERROR ("(format type/name for the constructor)");
-      return StatusCode::FAILURE;
-    }
+  }
+
+
+
+  template <typename T>
+  std::ostream& operator << (std::ostream& str, const AnaToolHandle<T>& obj)
+  {
+    return str << obj.getHandle();
+  }
+
+
+
+  template<class T> void AnaToolHandle<T> ::
+  testInvariant () const
+  {
+#define CHECK_INVARIANT(x)			\
+    if (!(x)) { std::cerr << __FILE__ << ":" << __LINE__ << ": invariant violated: " << #x << std::endl; std::abort(); }
+
+    // General requirements
+    CHECK_INVARIANT (&*this != nullptr);
+    CHECK_INVARIANT (m_handleUser != nullptr);
+    // CHECK_INVARIANT (m_parentPtr == nullptr || m_parentPtr->name() == m_parentName);
+    // #ifndef ROOTCORE
+    // CHECK_INVARIANT (m_parentPtr == m_handleUser->parent());
+    // #endif
 
-    return doMake ();
+#undef CHECK_INVARIANT
   }
 
 
 
-  template <class T> template <class T2>
-  StatusCode AnaToolHandle<T> ::
-  setProperty (const std::string& property, const T2& value)
+  template<class T> AnaToolHandle<T> ::
+  AnaToolHandle (const std::string& val_name, parentType_t *val_parent)
+    : m_parentName (val_parent ? val_parent->name() : std::string()),
+      m_parentPtr (val_parent),
+      m_handleUser (new ToolHandle<T> (val_name, val_parent)),
+      m_originalTypeAndName (m_handleUser->typeAndName ()),
+      m_allowEmpty (val_name.empty())
   {
-    using namespace msgToolHandle;
+    setTypeAndName (val_name);
 
 #ifndef NDEBUG
     this->testInvariant ();
 #endif
-    ANA_CHECK (preSetProperty (property));
-    if (m_state != State::CREATED && m_state != State::BAD_PROPERTY)
+  }
+
+
+
+  template<class T> AnaToolHandle<T> ::
+  AnaToolHandle (AnaToolHandle<T>&& that)
+    : AnaToolHandle ()
+  {
+    swap (that);
+  }
+
+
+
+  template<class T> AnaToolHandle<T> ::
+  AnaToolHandle (const AnaToolHandle<T>& that)
+    : m_config (that.m_config),
+      m_name (that.m_name),
+      m_parentName (that.m_parentName),
+      m_parentPtr (that.m_parentPtr),
+      m_handleUser (new ToolHandle<T> (*that.m_handleUser)),
+      m_originalTypeAndName (that.m_originalTypeAndName),
+      m_isInitialized (that.m_isInitialized.load()),
+      m_allowEmpty (that.m_allowEmpty)
+  {
+    if (m_isInitialized.load())
     {
-#ifndef NDEBUG
-      testInvariant ();
-#endif
-      return StatusCode::SUCCESS;
+      m_toolPtr = that.m_toolPtr;
+      m_mode = that.m_mode;
+      m_cleanup = that.m_cleanup;
     }
 
-#ifdef ROOTCORE
+#ifndef ROOTCORE
+    if (!m_handleUser->empty())
+      (*m_handleUser)->release();
+#endif
 
-    // Call setProperty on our cached tool pointer
-    if (m_toolConfig->setProperty (property, value).isFailure())
-      m_state = State::BAD_PROPERTY;
 #ifndef NDEBUG
+    that.testInvariant ();
     testInvariant ();
 #endif
-    return StatusCode::SUCCESS;
+  }
 
-#else
 
-    m_addedProperties.push_back(property); //this is so we clear out properties from catalogue when tool is destroyed
 
-    //for athena we hand our property to the joboptions svc
-    const std::string val = Gaudi::Utils::toString ( value ) ;
-    return detail::addPropertyToCatalogue( fullName() , property, val );
-#endif
+  template<class T> AnaToolHandle<T>& AnaToolHandle<T> ::
+  operator = (const AnaToolHandle<T>& that)
+  {
+    // no invariant used
+    AnaToolHandle<T> (that).swap (*this);
+    return *this;
   }
 
 
 
-  template <class T> template <class T2>
-  StatusCode AnaToolHandle<T> ::
-  setProperty (const std::string& property, const ToolHandle<T2>& toolHandle)
+  template<class T> void AnaToolHandle<T> ::
+  swap (AnaToolHandle<T>& that) noexcept
   {
-    using namespace msgToolHandle;
 #ifndef NDEBUG
-    this->testInvariant ();
+    testInvariant ();
+    that.testInvariant ();
 #endif
 
-    if (toolHandle.empty())
+    m_cleanup.swap (that.m_cleanup);
+    m_config.swap (that.m_config);
+    m_name.swap (that.m_name);
+    m_parentName.swap (that.m_parentName);
+    std::swap (m_parentPtr, that.m_parentPtr);
     {
-      ANA_MSG_ERROR ("trying to initialize ToolHandle property " << property << " with empty handle");
-#ifndef NDEBUG
-      testInvariant ();
+      ToolHandle<T> tmp = *m_handleUser;
+#ifndef ROOTCORE
+      if (!tmp.empty())
+        tmp->release();
 #endif
-      return StatusCode::FAILURE;
+      *m_handleUser = *that.m_handleUser;
+      *that.m_handleUser = tmp;
     }
-
-    ANA_CHECK (preSetProperty (property));
-    if (m_state != State::CREATED && m_state != State::BAD_PROPERTY)
+    m_originalTypeAndName.swap (that.m_originalTypeAndName);
     {
-#ifndef NDEBUG
-      testInvariant ();
-#endif
-      return StatusCode::SUCCESS;
+      const auto tmp = m_isInitialized.load();
+      m_isInitialized = that.m_isInitialized.load();
+      that.m_isInitialized = tmp;
     }
+    std::swap (m_toolPtr, that.m_toolPtr);
+    std::swap (m_mode, that.m_mode);
+    std::swap (m_allowEmpty, that.m_allowEmpty);
 
-#ifdef ROOTCORE
-
-    // Call setProperty on our cached tool pointer
-    if (m_toolConfig->setProperty (property, toolHandle).isFailure())
-      m_state = State::BAD_PROPERTY;
 #ifndef NDEBUG
     testInvariant ();
+    that.testInvariant ();
 #endif
-    return StatusCode::SUCCESS;
-
-    /*
-    // Call setProperty on our cached tool pointer.
-    // This only works in RootCore because the tool pointer constructor
-    // form doesn't exist in Athena.
-    return m_toolConfig->setProperty (property, &*toolHandle);
-    */
-
-#else
+  }
 
-    auto tool = toolHandle.get();
 
-    //tool must already exist in the ToolSvc
-    if(tool==nullptr) {
-        ANA_MSG_ERROR("Tool " << toolHandle.typeAndName() << " must be initialized before you can pass it to another tool with setProperty");
-        return StatusCode::FAILURE;
-    }
 
-    //strip the parent name
-    std::string tool_name = toolHandle.name();
-    if(tool_name.find(name()+".")==0) {
-      //we also strip the name of our tool, if it appears at the front of tool_name ...
-      //this is so private subtools can be set with code like:
-      //ATH<> subtool("MyTool/ParentTool.SubTool");
-      //ATH<> parenttool("MyTool2/ParentTool");
-      //parenttool.setProperty("SubToolProperty",subtool);
-      tool_name.replace(0,name().size()+1,"");
-    } 
-
-    return setProperty( property, tool->type() + "/" + tool_name );
-#endif
+  template<class T> AnaToolHandle<T>& AnaToolHandle<T> ::
+  operator = (AnaToolHandle<T>&& that)
+  {
+    // no invariant used
+    swap (that);
+    return *this;
   }
 
 
 
-#ifndef ROOTCORE
-
-template <class T> template <class T2>
-  StatusCode AnaToolHandle<T> ::
-  setProperty (const std::string& property, const ToolHandleArray<T2>& toolHandleArray)
+  template<class T> AnaToolHandle<T> ::
+  ~AnaToolHandle () noexcept
   {
     using namespace msgToolHandle;
 #ifndef NDEBUG
     this->testInvariant ();
 #endif
+  }
 
-    
 
-    ANA_CHECK (preSetProperty (property));
-    if (m_state != State::CREATED && m_state != State::BAD_PROPERTY)
-    {
+  template<class T> bool
+  AnaToolHandle<T> ::
+  empty () const
+  {
 #ifndef NDEBUG
-      testInvariant ();
+     this->testInvariant ();
 #endif
-      return StatusCode::SUCCESS;
+    switch (getMode())
+    {
+    case detail::AnaToolHandleMode::EMPTY:
+      return true;
+    case detail::AnaToolHandleMode::CREATE_PRIVATE:
+    case detail::AnaToolHandleMode::CREATE_SHARED:
+    case detail::AnaToolHandleMode::RETRIEVE_SHARED:
+      return false;
+    case detail::AnaToolHandleMode::USER:
+      return m_handleUser->empty();
     }
+    return false; //compiler dummy
+  }
 
-    std::vector<std::string> tools;
-    //loop over toolhandles in array, strip off any parent naming and set property with the result
-    for(auto& toolHandle : toolHandleArray) {
-      if (toolHandle.empty())
-      {
-        ANA_MSG_ERROR ("trying to initialize ToolHandle property " << property << " with empty handle");
-  #ifndef NDEBUG
-        testInvariant ();
-  #endif
-        return StatusCode::FAILURE;
-      }
 
-       auto tool = toolHandle.get();
-      if(tool == nullptr) {
-        ANA_MSG_ERROR("Tool " << toolHandle.typeAndName() << " must be initialized before you can pass it to another tool with setProperty");
-        return StatusCode::FAILURE;
-      }
-      
-      //strip the parent name
-      std::string tool_name = toolHandle.name();
-      if(tool_name.find(name()+".")==0) {
-        //we also strip the name of our tool, if it appears at the front of tool_name ...
-        //this is so private subtools can be set with code like:
-        //ATH<> subtool("MyTool/ParentTool.SubTool");
-        //ATH<> parenttool("MyTool2/ParentTool");
-        //parenttool.setProperty("SubToolProperty",subtool);
-        tool_name.replace(0,name().size()+1,"");
-      } 
-      
-      tools.push_back( tool->type() + "/" + tool_name );
-      
-    }
 
-    return setProperty( property, tools );
+  template<class T> inline bool AnaToolHandle<T> ::
+  isPublic () const noexcept
+  {
+#ifndef NDEBUG
+     this->testInvariant ();
+#endif
+     return m_parentName.empty();
   }
 
+
+
+   template<class T> inline const std::string& AnaToolHandle<T> ::
+   type () const noexcept
+   {
+#ifndef NDEBUG
+     this->testInvariant ();
+#endif
+     return m_config.type();
+   }
+
+
+
+   template<class T> inline const std::string&
+   AnaToolHandle<T> ::
+   name () const noexcept
+   {
+#ifndef NDEBUG
+     this->testInvariant ();
 #endif
+     return m_name;
+   }
+
 
 
   template <class T> template <class T2>
   StatusCode AnaToolHandle<T> ::
-  setProperty (const std::string& property, const AnaToolHandle<T2>& toolHandle)
+  setProperty (const std::string& property, const T2& value)
   {
     using namespace msgToolHandle;
-    // no invariant used
 
-    if (!toolHandle.isInitialized())
+#ifndef NDEBUG
+    this->testInvariant ();
+    if (isInitialized())
     {
-      ANA_MSG_ERROR ("need to pass initialized tool handle into setProperty");
-      return StatusCode::FAILURE;
+      ANA_MSG_FATAL ("AnaToolHandle has already been initialized: " << *this);
+      std::abort();
     }
-
-#ifdef ROOTCORE
-    return setProperty (property, ToolHandle<T2> (toolHandle.get()));
-#else
-    return setProperty (property, toolHandle.getHandle());
 #endif
+
+    return m_config.setProperty (property, value);
   }
 
 
@@ -508,72 +797,66 @@ template <class T> template <class T2>
   {
     using namespace msgToolHandle;
 
+    // ensure we don't initialize twice concurrently
+    std::lock_guard<std::recursive_mutex> lock (m_initializeMutex);
+
 #ifndef NDEBUG
     this->testInvariant ();
-#endif
-    switch (m_state)
+    if (isInitialized())
     {
-    case State::BEGIN:
-       // make the tool, this can cause our state to switch to
-       // PREINITIALIZED, if the tool we are setup to make is actually
-       // coming from user config or is shared
-      ANA_CHECK (make());
-      assert (m_state != State::BEGIN);
-      return initialize ();
-    case State::PREINITIALIZED:
-      // we are using a tool that already has already been
-      // initialized, so all we need to do is change state
-      m_state = State::INITIALIZED;
-#ifndef NDEBUG
-      this->testInvariant ();
-#endif
-      return StatusCode::SUCCESS;
-    case State::CREATED:
-      // ok, tool created but not initialized, can initialize
-      break;
-    case State::INITIALIZED:
-      ANA_MSG_ERROR ("tool " << *this << " has already been initialized");
-      std::abort ();
-    case State::BAD_PROPERTY:
-      ANA_MSG_ERROR ("encountered error setting properties on " << *this << " refusing to initialize");
-      m_state = State::BROKEN;
-      return StatusCode::FAILURE;
-    case State::BROKEN:
-      ANA_MSG_ERROR ("tool handle " << *this << " in broken state");
-      return StatusCode::FAILURE;
+      ANA_MSG_FATAL ("AnaToolHandle has already been initialized: " << *this);
+      std::abort();
     }
+#endif
 
-    // first setting state to broken, so if we fail it stays broken
-    m_state = State::BROKEN;
-
-
-#ifdef ROOTCORE
+    std::shared_ptr<detail::AnaToolShare> sharedTool;
+    const detail::AnaToolHandleMode mode = getMode (sharedTool);
 
-    ANA_CHECK (m_toolPtr->initialize());
+    ToolHandle<T> th;
+    detail::AnaToolCleanup cleanup;
 
-    if (m_parent == nullptr)
+    switch (mode)
     {
-      auto& pointer = sharedToolPointer ();
-      assert (pointer.lock() == nullptr);
-      pointer = m_toolOwn;
-      assert (sharedToolPointer ().lock() == m_toolOwn);
+    case detail::AnaToolHandleMode::EMPTY:
+      break;
+    case detail::AnaToolHandleMode::CREATE_PRIVATE:
+      ANA_CHECK (m_config.makeTool (m_name, m_parentPtr, th, cleanup));
+      break;
+    case detail::AnaToolHandleMode::CREATE_SHARED:
+      ANA_CHECK (detail::AnaToolShareList::singleton().makeShare (m_name, m_config, sharedTool));
+      // no break
+    case detail::AnaToolHandleMode::RETRIEVE_SHARED:
+      assert (sharedTool != nullptr);
+      ANA_CHECK (detail::toolHandleCast (th, sharedTool->th()));
+#ifndef ROOTCORE
+      if (!th.empty())
+        th->release ();
+#endif
+      cleanup.addCleanup (sharedTool);
+      break;
+    case detail::AnaToolHandleMode::USER:
+      th = *m_handleUser;
+      if (th.empty() && !m_allowEmpty)
+      {
+	ANA_MSG_ERROR ("user configured an empty handle for a non-empty AnaToolHandle: " << *this);
+	return StatusCode::FAILURE;
+      }
+      break;
     }
 
-#else
-
-    //in athena, before retrieving, we inspect the joboptionssvc for properties matching my property name, and copies those over
-    ANA_CHECK( detail::copyPropertiesInCatalogue( m_handle->parentName() + "." + name() , fullName() ) );
-
-    //just 'retrieve' the toolhandle .. if fails, then go broken
-    ANA_CHECK (m_handle->retrieve());
-
-    //must increment refcount on the tool (get two refcounts automatically, one for ToolSvc, and *i think* one for HistorySvc (yuck)
-    //(*m_handle)->addRef();
-    m_toolPtr = &**m_handle;
+    T *toolPtr = nullptr;
+    ANA_CHECK (makeToolRetrieve (toolPtr, th));
 
+    *m_handleUser = th;
+#ifndef ROOTCORE
+    if (!th.empty())
+      th->release ();
 #endif
+    m_mode = mode;
+    m_cleanup.swap (cleanup);
+    m_toolPtr = toolPtr;
+    m_isInitialized = true;
 
-    m_state = State::INITIALIZED;
 #ifndef NDEBUG
     this->testInvariant ();
 #endif
@@ -599,41 +882,69 @@ template <class T> template <class T2>
 #ifndef NDEBUG
     this->testInvariant ();
 #endif
-    return // !empty() && 
-#ifdef ROOTCORE
-      // !(m_parent == nullptr && sharedToolPointer().lock() != nullptr) &&
-      // !(m_parent == nullptr && !name().empty() && ToolStore::contains<T> (name())) &&
+    switch (getMode())
+    {
+    case detail::AnaToolHandleMode::EMPTY:
+    case detail::AnaToolHandleMode::CREATE_PRIVATE:
+    case detail::AnaToolHandleMode::CREATE_SHARED:
+      return true;
+    case detail::AnaToolHandleMode::RETRIEVE_SHARED:
+    case detail::AnaToolHandleMode::USER:
+      return false;
+    }
+    return true; //compiler dummy
+  }
+
+
+
+  template<class T>
+#ifndef NDEBUG
+  inline
 #endif
-      !isUserConfigured ();
+  bool AnaToolHandle<T> ::
+  isInitialized () const noexcept
+  {
+#ifndef NDEBUG
+    this->testInvariant ();
+#endif
+    return m_isInitialized;
+  }
+
+
+
+  template<class T> inline T *
+  AnaToolHandle<T> ::
+  operator -> ()
+  {
+    // no invariant used
+    return get ();
   }
 
 
 
-  template<class T> bool
+  template<class T> inline const T *
   AnaToolHandle<T> ::
-  isInitialized () const noexcept
+  operator -> () const
   {
-#ifndef NDEBUG
-    this->testInvariant ();
-#endif
-    return (m_state == State::INITIALIZED); 
+    // no invariant used
+    return get ();
   }
 
 
 
-  template<class T> inline T *
+  template<class T> inline T&
   AnaToolHandle<T> ::
-  operator -> () const noexcept
+  operator * ()
   {
     // no invariant used
-    return get ();
+    return *get ();
   }
 
 
 
-  template<class T> inline T&
+  template<class T> inline const T&
   AnaToolHandle<T> ::
-  operator * () const noexcept
+  operator * () const
   {
     // no invariant used
     return *get ();
@@ -643,32 +954,35 @@ template <class T> template <class T2>
 
   template<class T> inline T*
   AnaToolHandle<T> ::
-  get () const noexcept
+  get ()
   {
     using namespace msgToolHandle;
 
 #ifndef NDEBUG
     this->testInvariant ();
 #endif
-    switch (m_state)
-    {
-    case State::BEGIN:
-    case State::PREINITIALIZED:
-    case State::CREATED:
-    case State::BAD_PROPERTY:
-      ANA_MSG_FATAL ("can't call get on handle " << *this << " without initialized tool");
-      std::abort();
-    case State::INITIALIZED:
-      break;
-    case State::BROKEN:
-      ANA_MSG_FATAL ("can't call get on handle " << *this << " which is in a broken state");
-      std::abort();
-    }
+
+    if (m_isInitialized.load())
+      return m_toolPtr;
+
+    std::lock_guard<std::recursive_mutex> lock (m_initializeMutex);
+    if (!m_isInitialized)
+      ANA_CHECK_THROW (initialize());
+    assert (m_isInitialized);
     return m_toolPtr;
   }
 
 
 
+  template<class T> inline const T*
+  AnaToolHandle<T> ::
+  get () const
+  {
+    return const_cast<AnaToolHandle<T>*>(this)->get();
+  }
+
+
+
   template <class T> template<typename T2> void
   AnaToolHandle<T> ::
   declarePropertyFor (T2 *tool, const std::string& name,
@@ -677,489 +991,348 @@ template <class T> template <class T2>
     using namespace msgToolHandle;
 #ifndef NDEBUG
     this->testInvariant ();
-#endif
-    switch (m_state)
+    if (isInitialized())
     {
-    case State::BEGIN:
-      break;
-    case State::PREINITIALIZED:
-    case State::CREATED:
-    case State::INITIALIZED:
-    case State::BAD_PROPERTY:
-    case State::BROKEN:
       ANA_MSG_FATAL ("can't declare tool handle " << *this << " as property " << name << " after tool has been instantiated");
       std::abort ();
     }
+#endif
 
-    if (m_parent != nullptr && m_parent != tool)
+    if (m_parentPtr != nullptr && m_parentPtr != tool)
     {
-      ANA_MSG_FATAL ("can't declare tool handle " << *this << " as property for tool " << tool->name() << " as it has a different parent tool " << m_parent->name());
+      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());
       std::abort ();
     }
-    ANA_CHECK_THROW (tool->declareProperty (name, *m_handle, description));
+    ANA_CHECK_THROW (tool->declareProperty (name, *m_handleUser, description));
   }
 
 
 
-  template <class T> bool
-  AnaToolHandle<T> ::
-  inPremakeState () const noexcept
-  {
-#ifndef NDEBUG
-    this->testInvariant ();
-#endif
-    switch (m_state)
-    {
-    case State::BEGIN:
-      return true;
-    case State::PREINITIALIZED:
-    case State::CREATED:
-    case State::INITIALIZED:
-    case State::BAD_PROPERTY:
-    case State::BROKEN:
-      return false;
-    }
-   return false; //compiler dummy
-  }
 
 
 
-  template <class T> bool
+  template <class T> const ToolHandle<T>&
   AnaToolHandle<T> ::
-  inBrokenState () const noexcept
+  getHandle () const noexcept
   {
 #ifndef NDEBUG
     this->testInvariant ();
 #endif
-    switch (m_state)
-    {
-    case State::BROKEN:
-      return true;
-    case State::BEGIN:
-    case State::PREINITIALIZED:
-    case State::CREATED:
-    case State::INITIALIZED:
-    case State::BAD_PROPERTY:
-      return false;
-    }
-      return false; //compiler dummy
+    return *m_handleUser;
   }
 
 
 
-  template <class T> const ToolHandle<T>&
-  AnaToolHandle<T> ::
-  getHandle () const noexcept
+#ifdef ROOTCORE
+  template <class T> template <class T2> void AnaToolHandle<T> ::
+  setTypeRegisterNew (std::string val_type)
   {
-#ifndef NDEBUG
-    this->testInvariant ();
-#endif
-    return *m_handle;
+    using namespace msgToolHandle;
+
+    m_config.registerNew<T2> ();
+    setType (std::move (val_type));
   }
+#endif
 
 
 
-  template <class T> ToolHandle<T>&
+  template <class T> bool
   AnaToolHandle<T> ::
-  handle ()
+  isUserConfigured () const noexcept
   {
+    using namespace msgToolHandle;
 #ifndef NDEBUG
     this->testInvariant ();
 #endif
-    return *m_handle;
+
+    switch (getMode())
+    {
+    case detail::AnaToolHandleMode::EMPTY:
+    case detail::AnaToolHandleMode::CREATE_PRIVATE:
+    case detail::AnaToolHandleMode::CREATE_SHARED:
+      return false;
+    case detail::AnaToolHandleMode::RETRIEVE_SHARED:
+    case detail::AnaToolHandleMode::USER:
+      return true;
+    }
+    return false; //compiler dummy
   }
 
 
 
-#ifdef ROOTCORE
-  template <class T> template <class T2> StatusCode
+  template<class T> std::string
   AnaToolHandle<T> ::
-  makeNew (std::string val_type)
+  fullName () const
   {
-    using namespace msgToolHandle;
-
-    ANA_CHECK (preMake (val_type));
-    if (m_state != State::BEGIN)
-    {
 #ifndef NDEBUG
-      this->testInvariant ();
+    this->testInvariant ();
 #endif
-      return StatusCode::SUCCESS;
-    }
-
-    // Create the tool
+#ifndef ROOTCORE
+    return m_handleUser->parentName() + "." + name();
+#else
     std::string toolName;
-    if (m_parent != nullptr)
-      toolName = m_parent->name() + "." + name();
+    if (!isPublic())
+      toolName = m_parentName + "." + name();
     else
       toolName = name();
-    std::unique_ptr<T2> tool (new T2 (toolName));
-    m_toolConfig = tool.get();
-    m_toolOwn = std::move (tool);
-    m_toolPtr = m_toolOwn.get();
-
-    // Inherit verbosity from parent
-    if (m_parent != nullptr)
-      m_toolConfig->msg().setLevel( m_parent->msg().level() );
-
-    setType (std::move (val_type));
-    m_state = State::CREATED;
-#ifndef NDEBUG
-    this->testInvariant ();
+    return toolName;
 #endif
-    return StatusCode::SUCCESS;
   }
-#endif
 
 
 
-  template <class T> bool
-  AnaToolHandle<T> ::
-  isUserConfigured () const noexcept
+  template<class T> detail::AnaToolHandleMode AnaToolHandle<T> ::
+  getMode (std::shared_ptr<detail::AnaToolShare>& sharedTool) const
   {
+    using namespace msgToolHandle;
 #ifndef NDEBUG
     this->testInvariant ();
 #endif
 
-    // we should have cached the value of \ref isUserConfigured in
-    // \ref make, so we shouldn't try again to check it, as the
-    // actions in \ref make may actually change the result of \ref
-    // isUserConfigured
-    if (m_state != State::BEGIN)
-      return m_isUserConfigured;
+    assert (!m_isInitialized);
 
-    if (m_handle->isSet())
-      return true;
+    if (m_handleUser->isSet())
+      return detail::AnaToolHandleMode::USER;
 
-    if (m_handle->typeAndName() != m_originalTypeAndName)
-      return true;
+    if (m_handleUser->typeAndName() != m_originalTypeAndName)
+      return detail::AnaToolHandleMode::USER;
 
 #ifdef ROOTCORE
-    if (m_parent != nullptr)
+    if (!m_parentName.empty())
     {
-      if (m_handle->parentName() != m_parent->name())
-	return true;
+      if (m_handleUser->parentName() != m_parentName)
+	return detail::AnaToolHandleMode::USER;
     } else
     {
-      if (m_handle->parentName() != "ToolSvc")
-	return true;
-      if (!name().empty())
-      {
-	if (ToolStore::contains<T> (name()))
-	  return true;
-	if (sharedToolPointer().lock() != nullptr)
-	  return true;
-      }
+      if (m_handleUser->parentName() != "ToolSvc")
+	return detail::AnaToolHandleMode::USER;
     }
 #endif
 
+    if (isPublic())
+    {
+      if ((sharedTool = detail::AnaToolShareList::singleton()
+	     .getShare (fullName())))
+	return detail::AnaToolHandleMode::RETRIEVE_SHARED;
+#ifdef ROOTCORE
+      /// \todo check whether this is actually what we want to do
+      if (ToolStore::contains<T> (m_handleUser->name()))
+	return detail::AnaToolHandleMode::USER;
+#endif
+    }
+
 #ifndef ROOTCORE
     //for athena, all we do here is check if the tool already exists
     interfaceType_t *tool = nullptr;
     if( detail::toolExists( fullName(), tool ) )
-      return true;
+      return detail::AnaToolHandleMode::USER;
 
     if (detail::hasPropertiesInCatalogue (fullName()))
-      return true;
+      return detail::AnaToolHandleMode::USER;
 #endif
 
-    return false;
-    /*
+    if (m_config.empty() && m_name.empty())
+      return detail::AnaToolHandleMode::EMPTY;
 
-    if (m_handle == nullptr)
-      return false;
-#ifdef ROOTCORE
-    return !m_handle->empty();
-#else
-   //here we exploit quirk that users who set our handle from another handle
-   // will get a typeName with the words 'PublicToolHandle' or 'PrivateToolHandle' 
-   // at the start of the typeAndName, so we can detect it that way
-    if ( 
-      (strncmp(m_handle->typeAndName().c_str(), "PublicToolHandle", strlen("PublicToolHandle")) == 0) ||
-      (strncmp(m_handle->typeAndName().c_str(), "PrivateToolHandle", strlen("PrivateToolHandle")) == 0)
-      ) return true;
-    //must also check the joboptions service for properties 
-    ServiceHandle<IJobOptionsSvc> svc("JobOptionsSvc","AnaToolHandle");
-    if( svc.retrieve().isFailure() ) return false;
-    if( svc->getProperties(m_handle->parentName() + "." + m_handle->name()) ) return true;
-    svc.release().ignore();
-    return false;
+    if (isPublic())
+      return detail::AnaToolHandleMode::CREATE_SHARED;
+    else
+      return detail::AnaToolHandleMode::CREATE_PRIVATE;
 
 
-#endif
+    /// \todo check whether we still need any of this code to determin
+    /// if a tool handle is empty
+    /*
+    //handle is empty if: it wasn't user configured and our type and name are not set, or it is user configured and the member handle is empty
+    return( (  isUserConfigured() && ( m_handleUser->empty() || m_handleUser->typeAndName()=="PublicToolHandle('')" || m_handleUser->typeAndName()=="PrivateToolHandle('')" ) )
+	    || ( (!isUserConfigured() && type()=="" && name()=="") ) );
     */
   }
 
 
-  template <class T> StatusCode
-  AnaToolHandle<T> ::
-  preSetProperty (const std::string& property)
+
+  template<class T> detail::AnaToolHandleMode AnaToolHandle<T> ::
+  getMode () const
   {
-    using namespace msgToolHandle;
+    if (m_isInitialized)
+      return m_mode;
+
+    std::shared_ptr<detail::AnaToolShare> sharedTool;
+    return getMode (sharedTool);
+  }
+
 
+
+  template<class T> std::string AnaToolHandle<T> ::
+  typeAndName () const
+  {
 #ifndef NDEBUG
     this->testInvariant ();
 #endif
-    switch (m_state)
-    {
-    case State::BEGIN:
-      ANA_CHECK (make());
-      return preSetProperty (property);
-    case State::PREINITIALIZED:
-      // we are using a tool that already has all its properties set
-      // and initialized, so we are not doing that again
-      ANA_MSG_INFO ("Ignoring setProperty for " << *this << "." << property << " - tool preInitialized");
-      return StatusCode::SUCCESS;
-    case State::CREATED:
-    case State::BAD_PROPERTY:
-      // ok, tool created but not initialized, can set properties
-      return StatusCode::SUCCESS;
-    case State::INITIALIZED:
-      ANA_MSG_FATAL ("tool " << *this << " has already been initialized");
-      std::abort ();
-    case State::BROKEN:
-      ANA_MSG_ERROR ("tool handle " << *this << " in broken state");
-      return StatusCode::FAILURE;
-    }
-    return StatusCode::FAILURE; //compiler dummy
+    if (name().empty())
+      return m_config.type();
+    if (m_config.type().empty())
+      return name();
+    return m_config.type() + "/" + name();
   }
 
 
 
-  template <class T> StatusCode
-  AnaToolHandle<T> ::
-  preMake (const std::string& val_type)
+  template<class T> void AnaToolHandle<T> ::
+  setType (std::string val_type) noexcept
   {
     using namespace msgToolHandle;
-
 #ifndef NDEBUG
     this->testInvariant ();
-#endif
-
-    switch (m_state)
+    if (isInitialized())
     {
-    case State::BEGIN:
-      break;
-    case State::PREINITIALIZED:
-    case State::CREATED:
-    case State::INITIALIZED:
-    case State::BAD_PROPERTY:
-      ANA_MSG_FATAL ("tool " << *this << " has already been made, can't call make again");
-      std::abort ();
-    case State::BROKEN:
-      ANA_MSG_ERROR ("tool handle " << *this << " in broken state");
-      return StatusCode::FAILURE;
-    }
-
-#ifdef ROOTCORE
-    // this ensures that in RootCore we can share public tools when
-    // requested with the same name
-    if (m_parent == nullptr && m_handle->isSet() == false &&
-	!name().empty())
-    {
-      m_isUserConfigured = true;
-      m_toolOwn = sharedToolPointer().lock();
-      m_toolPtr = m_toolOwn.get();
-      if (m_toolPtr != nullptr)
-      {
-        // this is right: PREINITIALIZED means that we rely on a tool
-        // that has already been initialized by somebody else (another
-        // ToolHandle in this case).
-    	m_state = State::PREINITIALIZED;
-#ifndef NDEBUG
-    	this->testInvariant ();
-#endif
-    	return StatusCode::SUCCESS;
-      }
+      ANA_MSG_FATAL ("AnaToolHandle has already been initialized: " << *this);
+      std::abort();
     }
 #endif
+    m_config.setType (std::move (val_type));
+  }
 
-    if ((m_isUserConfigured = isUserConfigured()))
-    {
-      m_state = State::BROKEN;
-      try
-      {
-	m_toolPtr = &**m_handle;
-	if (m_toolPtr == nullptr)
-	{
-	  ANA_MSG_ERROR ("failed to retrieve tool from tool handle " << *m_handle);
-	  return StatusCode::FAILURE;
-	}
-      } catch (std::exception& e)
-      {
-	ANA_MSG_ERROR ("encountered exception during tool retrieval (" <<
-		       *m_handle << "): " << e.what());
-	return StatusCode::FAILURE;
-      }
-      m_state = State::PREINITIALIZED;
-#ifndef NDEBUG
-      testInvariant ();
-#endif
-      return StatusCode::SUCCESS;
-    }
-
-    if (!val_type.empty())
-    {
-      if (val_type.find ('/') != std::string::npos)
-	setTypeAndName (val_type);
-      else
-	setType (val_type);
-    }
 
-    if (type().empty())
-    {
-      ANA_MSG_ERROR ("no type specified for ToolHandle");
-      return StatusCode::FAILURE;
-    }
 
-    if (name().empty())
+  template<class T> void AnaToolHandle<T> ::
+  setName (std::string val_name) noexcept
+  {
+    using namespace msgToolHandle;
+#ifndef NDEBUG
+    this->testInvariant ();
+    if (isInitialized())
     {
-      ANA_MSG_ERROR ("no name specified for ToolHandle");
-      return StatusCode::FAILURE;
+      ANA_MSG_FATAL ("AnaToolHandle has already been initialized: " << *this);
+      std::abort();
     }
-
-    return StatusCode::SUCCESS;
-
-    /*
-#ifndef ROOTCORE
-      //check form of typeAndName ... if it is "PublicToolHandle('AAA/BBB')" then we need to parse it
-      std::string mytype = m_handle->typeAndName();
-      if(strncmp(mytype.c_str(), "PublicToolHandle(", strlen("PublicToolHandle(")) == 0) {
-         mytype.replace(0,18,""); mytype.replace(strlen(mytype.c_str())-2,2,""); 
-	 /// \todo check against original implementation
-	 *m_handle = ToolHandle<T>(mytype, 0); //turn our handle public!
-      } else if(strncmp(mytype.c_str(), "PrivateToolHandle(", strlen("PrivateToolHandle(")) == 0) {
-         mytype.replace(0,19,""); mytype.replace(strlen(mytype.c_str())-2,2,""); 
-	 /// \todo check against original implementation
-	 *m_handle = ToolHandle<T>(mytype, m_parent);
-      } else if(strncmp(mytype.c_str(), "PublicToolHandleHack(", strlen("PublicToolHandleHack(")) == 0) { //hack case for when setPropertyToolHandle has been used
-         mytype.replace(0,22,""); mytype.replace(strlen(mytype.c_str())-2,2,""); 
-         ///we don't replace the toolhandle because we need the original 'hacked' toolhandle
-      }
 #endif
 
-#ifndef ROOTCORE
-  //for athena, all we do here is check if the tool already exists, marking it preinitialized if so
-interfaceType_t* tool(0);
-if( detail::toolExists( fullName(), tool ) ) {
-//verify the tool is correct type
-if(tool->type() != m_handle->type()) {
-ANA_MSG_FATAL(" Tool of type " << tool->type() << " called " << tool->name() << " already exists. Cannot create tool with same name of type " << m_handle->type());
+    m_name = std::move (val_name);
+
 #ifndef NDEBUG
-this->testInvariant ();
-#endif
-return StatusCode::FAILURE;
-}
-m_state = State::PREINITIALIZED;
-m_toolPtr = &*m_handle;
-}
+    this->testInvariant ();
 #endif
-
-    */
   }
 
 
 
-#ifdef ROOTCORE
-  template<class T> inline std::weak_ptr<T>& AnaToolHandle<T> ::
-  sharedToolPointer () const
+  template<class T> void AnaToolHandle<T> ::
+  setTypeAndName (const std::string& val_typeAndName)
   {
+    using namespace msgToolHandle;
 #ifndef NDEBUG
-    this->testInvariant ();
+    if (isInitialized())
+    {
+      ANA_MSG_FATAL ("AnaToolHandle has already been initialized: " << *this);
+      std::abort();
+    }
 #endif
-    assert (!name().empty());
-    static std::map<std::string,std::weak_ptr<T>> toolMap;
-    return toolMap[name()];
+    auto split = val_typeAndName.find ("/");
+    if (split != std::string::npos)
+    {
+      setTypeAndName (val_typeAndName.substr (0, split),
+		      val_typeAndName.substr (split+1));
+    } else
+    {
+      setTypeAndName (val_typeAndName, val_typeAndName);
+    }
   }
-#endif
 
 
 
-#ifndef ROOTCORE
-  template<class T> std::string
-  AnaToolHandle<T> ::
-  fullName () const
+  template<class T> void AnaToolHandle<T> ::
+  setTypeAndName (std::string val_type, std::string val_name) noexcept
   {
+    using namespace msgToolHandle;
 #ifndef NDEBUG
-    this->testInvariant ();
+    if (isInitialized())
+    {
+      ANA_MSG_FATAL ("AnaToolHandle has already been initialized: " << *this);
+      std::abort();
+    }
 #endif
-    return m_handle->parentName() + "." + name();
+    setType (std::move (val_type));
+    setName (std::move (val_name));
   }
-#endif
 
 
 
-  template<class T> StatusCode
-  AnaToolHandle<T> ::
-  doMake ()
+  template<class T> StatusCode AnaToolHandle<T> ::
+  makeToolRetrieve
+    (T*& toolPtr, ToolHandle<T>& toolHandle) const
   {
     using namespace msgToolHandle;
 
-#ifdef ROOTCORE
-
-    // Call the Athena helper function to invoke the tool factory.
-    AsgTool *toolPtr = nullptr;
-
-    std::string toolName;
-    if (m_parent != nullptr)
-      toolName = m_parent->name() + "." + name();
-    else
-      toolName = name();
+    if (toolHandle.empty())
+    {
+      toolPtr = nullptr;
+      return StatusCode::SUCCESS;
+    }
 
     try
     {
-      ANA_CHECK (detail::makeToolRootCore (type(), toolName, toolPtr));
+      toolPtr = &*toolHandle;
+      if (toolPtr == nullptr)
+      {
+	ANA_MSG_ERROR ("failed to retrieve tool from tool handle " << *m_handleUser);
+	return StatusCode::FAILURE;
+      }
+      return StatusCode::SUCCESS;
     } catch (std::exception& e)
     {
-      ANA_MSG_ERROR ("encountered exception during tool creation(" <<
-		     type() << "," << name() << "): " << e.what());
-      m_state = State::BROKEN;
-#ifndef NDEBUG
-      this->testInvariant ();
-#endif
+      ANA_MSG_ERROR ("encountered exception during tool retrieval (" << toolHandle << "): " << e.what());
       return StatusCode::FAILURE;
     }
-    if (toolPtr == nullptr)
-    {
-      ANA_MSG_FATAL ("failed to allocate tool: " + type());
-      m_state = State::BROKEN;
+  }
+
+
+
+  template<class T> detail::AnaToolHandleMode AnaToolHandle<T> ::
+  mode () const
+  {
 #ifndef NDEBUG
-      this->testInvariant ();
+    this->testInvariant ();
 #endif
-      return StatusCode::FAILURE;
-    }
+    return getMode ();
+  }
 
-    // Try to cast to the requested interface
-    m_toolOwn.reset (dynamic_cast<T*>(toolPtr));
-    m_toolPtr = m_toolOwn.get();
-    if (m_toolPtr == nullptr)
-    {
-      assert (toolPtr != nullptr);
-      delete toolPtr;
-      ANA_MSG_ERROR ("failed to cast tool of type " + type() + " to requested interface");
-      m_state = State::BROKEN;
+
+
+  template<class T> const detail::AnaToolConfig& AnaToolHandle<T> ::
+  config () const
+  {
 #ifndef NDEBUG
-      this->testInvariant ();
+    this->testInvariant ();
 #endif
-      return StatusCode::FAILURE;
-    }
-
-    m_toolConfig = toolPtr;
+    return m_config;
+  }
 
-    // Inherit verbosity from parent ... in athena this is done by passing the parent in the factory method
-    if (m_parent != nullptr)
-      m_toolConfig->msg().setLevel( m_parent->msg().level() );
 
-#else
 
-    //tool doesn't exist, we should also check that we have the factory available for this type
-    // ANA_CHECK (detail::factoryExists( m_handle->type() ));
+  template<class T> bool AnaToolHandle<T> ::
+  allowEmpty () const noexcept
+  {
+#ifndef NDEBUG
+    this->testInvariant ();
 #endif
+    return m_allowEmpty;
+  }
+
 
-    m_state = State::CREATED;
+
+  template<class T> void AnaToolHandle<T> ::
+  setAllowEmpty (bool val_allowEmpty) noexcept
+  {
+    using namespace msgToolHandle;
 #ifndef NDEBUG
     this->testInvariant ();
+    if (isInitialized())
+    {
+      ANA_MSG_FATAL ("AnaToolHandle has already been initialized: " << *this);
+      std::abort();
+    }
 #endif
-    return StatusCode::SUCCESS;
+    m_allowEmpty = val_allowEmpty;
   }
 }
diff --git a/Control/AthToolSupport/AsgTools/AsgTools/AsgMetadataTool.h b/Control/AthToolSupport/AsgTools/AsgTools/AsgMetadataTool.h
index 4485e6ff8aebdd2a3b6498d8935d37d0f14b4ae4..548cdfa5d2d3a85ce433022699536f4d1e0bcfc0 100644
--- a/Control/AthToolSupport/AsgTools/AsgTools/AsgMetadataTool.h
+++ b/Control/AthToolSupport/AsgTools/AsgTools/AsgMetadataTool.h
@@ -1,5 +1,5 @@
 // Dear emacs, this is -*- c++ -*-
-// $Id: AsgMetadataTool.h 676319 2015-06-18 12:12:45Z krasznaa $
+// $Id: AsgMetadataTool.h 771072 2016-08-31 14:50:22Z krasznaa $
 #ifndef ASGTOOLS_ASGMETADATATOOL_H
 #define ASGTOOLS_ASGMETADATATOOL_H
 
@@ -41,8 +41,8 @@ namespace asg {
    ///
    /// @author Attila Krasznahorkay <Attila.Krasznahorkay@cern.ch>
    ///
-   /// $Revision: 676319 $
-   /// $Date: 2015-06-18 14:12:45 +0200 (Thu, 18 Jun 2015) $
+   /// $Revision: 771072 $
+   /// $Date: 2016-08-31 16:50:22 +0200 (Wed, 31 Aug 2016) $
    ///
    class AsgMetadataTool : public AsgTool,
                            public virtual IIncidentListener {
@@ -127,6 +127,10 @@ namespace asg {
       /// Object accessing the output metadata store
       mutable MetaStore_t m_outputMetaStore;
 
+      /// Flag helping to discover when the tool misses the opening of the first
+      /// input file
+      bool m_beginInputFileCalled;
+
    }; // class AsgMetadataTool
 
 } // namespace asg
diff --git a/Control/AthToolSupport/AsgTools/AsgTools/AsgTool.h b/Control/AthToolSupport/AsgTools/AsgTools/AsgTool.h
index db463ee70ab99a53882200c725701f87fae1c1e7..d539ed1d0916c267f0d49bca163a62bcdd8548cf 100644
--- a/Control/AthToolSupport/AsgTools/AsgTools/AsgTool.h
+++ b/Control/AthToolSupport/AsgTools/AsgTools/AsgTool.h
@@ -1,5 +1,5 @@
 // Dear emacs, this is -*- c++ -*-
-// $Id: AsgTool.h 741760 2016-04-20 20:12:12Z ssnyder $
+// $Id: AsgTool.h 790658 2016-12-20 20:54:19Z leggett $
 #ifndef ASGTOOLS_ASGTOOL_H
 #define ASGTOOLS_ASGTOOL_H
 
@@ -12,15 +12,15 @@
 #ifdef ASGTOOL_STANDALONE
 #   include "AsgTools/AsgMessaging.h"
 #   include "AsgTools/SgTEvent.h"
+   // Forward declaration(s):
+   class Property;
+   class PropertyMgr;
 #elif defined(ASGTOOL_ATHENA)
 #   include "AthenaBaseComps/AthAlgTool.h"
 #else
 #   error "What environment are we in?!?"
 #endif // Environment selection
 
-// Forward declaration(s):
-class Property;
-class PropertyMgr;
 
 namespace asg {
 
@@ -40,8 +40,8 @@ namespace asg {
    ///
    /// @author David Adams <dladams@bnl.gov>
    ///
-   /// $Revision: 741760 $
-   /// $Date: 2016-04-20 22:12:12 +0200 (Wed, 20 Apr 2016) $
+   /// $Revision: 790658 $
+   /// $Date: 2016-12-20 21:54:19 +0100 (Tue, 20 Dec 2016) $
    ///
    class AsgTool : public virtual IAsgTool,
                    public AsgToolBase {
diff --git a/Control/AthToolSupport/AsgTools/AsgTools/MessageCheck.h b/Control/AthToolSupport/AsgTools/AsgTools/MessageCheck.h
index 0c460c37ac091eec24533d3b04b986c6eecfa613..b309533d3d65742bedc82724daedd92bf3c3eaf2 100644
--- a/Control/AthToolSupport/AsgTools/AsgTools/MessageCheck.h
+++ b/Control/AthToolSupport/AsgTools/AsgTools/MessageCheck.h
@@ -78,9 +78,9 @@
 
 #include <type_traits>
 
+#include <xAODRootAccess/tools/TReturnCode.h>
 #ifdef ROOTCORE
 #include <AsgTools/MsgStream.h>
-#include <xAODRootAccess/tools/TReturnCode.h>
 #else
 #include "AthenaBaseComps/AthMessaging.h"
 #endif
@@ -199,7 +199,6 @@ namespace asg
       return StatusCode::FAILURE;}
   };
 
-#ifdef ROOTCORE
   template<> struct CheckHelper<xAOD::TReturnCode>
   {
     /// \brief whether the status code reports a success
@@ -214,7 +213,6 @@ namespace asg
     static inline decltype (xAOD::TReturnCode::kFailure) failureCode () {
       return xAOD::TReturnCode::kFailure;}
   };
-#endif
 
   template<> struct CheckHelper<int>
   {
diff --git a/Control/AthToolSupport/AsgTools/AsgTools/ToolHandle.h b/Control/AthToolSupport/AsgTools/AsgTools/ToolHandle.h
index c6d3bb5995ff48f0d701db7bb41a3d925a6257fe..2d13f3bf25bca8cf2a9b4eb4500dd50f1d1be020 100644
--- a/Control/AthToolSupport/AsgTools/AsgTools/ToolHandle.h
+++ b/Control/AthToolSupport/AsgTools/AsgTools/ToolHandle.h
@@ -1,5 +1,5 @@
 // Dear emacs, this is -*- c++ -*-
-// $Id: ToolHandle.h 724296 2016-02-16 16:24:42Z will $
+// $Id: ToolHandle.h 784417 2016-11-15 19:50:05Z krumnack $
 #ifndef ASGTOOLS_TOOLHANDLE_H
 #define ASGTOOLS_TOOLHANDLE_H
 
@@ -29,8 +29,8 @@ namespace asg {
 ///
 /// @author Attila Krasznahorkay <Attila.Krasznahorkay@cern.ch>
 ///
-/// $Revision: 724296 $
-/// $Date: 2016-02-16 17:24:42 +0100 (Tue, 16 Feb 2016) $
+/// $Revision: 784417 $
+/// $Date: 2016-11-15 20:50:05 +0100 (Tue, 15 Nov 2016) $
 ///
 class ToolHandleBase {
 
@@ -72,8 +72,8 @@ protected:
 /// @author David Adams <dladams@bnl.gov>
 /// @author Attila Krasznahorkay <Attila.Krasznahorkay@cern.ch>
 ///
-/// $Revision: 724296 $
-/// $Date: 2016-02-16 17:24:42 +0100 (Tue, 16 Feb 2016) $
+/// $Revision: 784417 $
+/// $Date: 2016-11-15 20:50:05 +0100 (Tue, 15 Nov 2016) $
 ///
 template< class T >
 class ToolHandle : public ToolHandleBase {
@@ -89,9 +89,13 @@ public:
    ToolHandle( const std::string& toolname, asg::IAsgTool* parent = 0 );
 
    /// Dereferencing operator
-   T& operator*() const;
+   T& operator*();
    /// Dereferencing operator
-   T* operator->() const;
+   const T& operator*() const;
+   /// Dereferencing operator
+   T* operator->();
+   /// Dereferencing operator
+   const T* operator->() const;
 
    /// Retrieve tool.
    /// For compatibility with Gaudi.
diff --git a/Control/AthToolSupport/AsgTools/AsgTools/ToolHandle.icc b/Control/AthToolSupport/AsgTools/AsgTools/ToolHandle.icc
index 378b6b8cabd8cc38d21f3027fd2a9d7ef7ef4661..01a90030113d7f09585c058e3e8e56a752771df5 100644
--- a/Control/AthToolSupport/AsgTools/AsgTools/ToolHandle.icc
+++ b/Control/AthToolSupport/AsgTools/AsgTools/ToolHandle.icc
@@ -1,5 +1,5 @@
 // Dear emacs, this is -*- c++ -*-
-// $Id: ToolHandle.icc 724348 2016-02-16 20:16:11Z krumnack $
+// $Id: ToolHandle.icc 784417 2016-11-15 19:50:05Z krumnack $
 #ifndef ASGTOOLS_TOOLHANDLE_ICC
 #define ASGTOOLS_TOOLHANDLE_ICC
 
@@ -26,7 +26,7 @@ ToolHandle< T >::ToolHandle( const std::string& typeAndName, asg::IAsgTool* pare
 }
 
 template< class T >
-T& ToolHandle< T >::operator*() const {
+T& ToolHandle< T >::operator*() {
 
    // Retrieve the tool pointer if necessary:
    if( ! m_ptool ) {
@@ -43,7 +43,41 @@ T& ToolHandle< T >::operator*() const {
 }
 
 template< class T >
-T* ToolHandle<T>::operator->() const {
+const T& ToolHandle< T >::operator*() const {
+
+   // Retrieve the tool pointer if necessary:
+   if( ! m_ptool ) {
+      m_ptool = asg::ToolStore::get< T >( name() );
+   }
+   // Check if we succeeded:
+   if( ! m_ptool ) {
+      throw std::runtime_error( "Couldn't find tool with name \"" +
+                                name() + "\"" );
+   }
+
+   // Return a reference to the tool:
+   return *m_ptool;
+}
+
+template< class T >
+T* ToolHandle<T>::operator->() {
+
+   // Retrieve the tool pointer if necessary:
+   if( ! m_ptool ) {
+      m_ptool = asg::ToolStore::get< T >( name() );
+   }
+   // Check if we succeeded:
+   if( ! m_ptool ) {
+      throw std::runtime_error( "Couldn't find tool with name \"" +
+                                name() + "\"" );
+   }
+
+   // Return the (possibly null-)pointer to the tool:
+   return m_ptool;
+}
+
+template< class T >
+const T* ToolHandle<T>::operator->() const {
 
    // Retrieve the tool pointer if necessary:
    if( ! m_ptool ) {
@@ -95,7 +129,7 @@ std::ostream& operator<<( std::ostream& out,
                           const ToolHandle< T >& handle ) {
 
    out << "ASG ToolHandle with name = \"" << handle.name() << "\", pointer = ";
-   T* ptool = nullptr;
+   const T* ptool = nullptr;
    if (handle.retrieve())
      ptool = handle.operator->();
    out << ptool;
diff --git a/Control/AthToolSupport/AsgTools/CMakeLists.txt b/Control/AthToolSupport/AsgTools/CMakeLists.txt
index 93faca157a9d7106c44551fbd41a167d3bc16194..73e7f42a3b48a04d111dd83ba7847f9e99a82fe5 100644
--- a/Control/AthToolSupport/AsgTools/CMakeLists.txt
+++ b/Control/AthToolSupport/AsgTools/CMakeLists.txt
@@ -1,4 +1,4 @@
-# $Id: CMakeLists.txt 745006 2016-05-05 10:40:32Z will $
+# $Id: CMakeLists.txt 790389 2016-12-18 13:39:12Z krumnack $
 ################################################################################
 # Package: AsgTools
 ################################################################################
@@ -12,7 +12,7 @@ if( XAOD_STANDALONE )
    set( deps Control/xAODRootAccessInterfaces Control/xAODRootAccess )
    set( libs xAODRootAccessInterfaces xAODRootAccess )
 else()
-   set( deps Control/AthenaBaseComps Control/SGTools Database/IOVDbDataModel
+   set( deps Control/xAODRootAccess Control/AthenaBaseComps Control/SGTools Database/IOVDbDataModel
       GaudiKernel )
    set( libs AthenaBaseComps SGTools IOVDbDataModel GaudiKernel )
 endif()
@@ -47,6 +47,12 @@ atlas_add_dictionary( AsgToolsDict
    AsgTools/AsgToolsDict.h AsgTools/selection.xml
    LINK_LIBRARIES AsgTools )
 
+# Silence some warnings that are generated by the code on MacOS X:
+set( extra_defs )
+if( APPLE AND TARGET AsgTools )
+   target_compile_options( AsgTools PUBLIC -Wno-tautological-undefined-compare )
+endif()
+
 # Test(s) in the package:
 atlas_add_test( gt_UnitTest_test
    SOURCES test/gt_UnitTest_test.cxx
diff --git a/Control/AthToolSupport/AsgTools/Root/AnaToolHandle.cxx b/Control/AthToolSupport/AsgTools/Root/AnaToolHandle.cxx
index 1020e48ff8fede41bd53c60830d1e1edaee3e465..8eb992aa14ad381b2090765e84da60711d5a3ea9 100644
--- a/Control/AthToolSupport/AsgTools/Root/AnaToolHandle.cxx
+++ b/Control/AthToolSupport/AsgTools/Root/AnaToolHandle.cxx
@@ -30,6 +30,99 @@
 // method implementations
 //
 
+namespace asg
+{
+  namespace detail
+  {
+    AnaToolShare ::
+    AnaToolShare (const ToolHandle<interfaceType_t>& val_th,
+		  AnaToolCleanup val_cleanup)
+      : m_th (val_th), m_cleanup (std::move (val_cleanup))
+    {
+      assert (!m_th.empty());
+    }
+
+
+
+    ToolHandle<interfaceType_t>& AnaToolShare ::
+    th ()
+    {
+      assert (!m_th.empty());
+      return m_th;
+    }
+
+
+
+    AnaToolShareList& AnaToolShareList ::
+    singleton () noexcept
+    {
+      static AnaToolShareList result;
+      return result;
+    }
+
+
+
+    std::shared_ptr<AnaToolShare> AnaToolShareList ::
+    getShare (const std::string& name) const
+    {
+      auto iter = m_shared.find (name);
+      if (iter == m_shared.end())
+	return std::shared_ptr<AnaToolShare> ();
+      return iter->second.lock();
+    }
+
+
+
+    std::shared_ptr<AnaToolShare> AnaToolShareList ::
+    setShare (const std::string& name,
+	      std::unique_ptr<AnaToolShare> val_share)
+    {
+      std::shared_ptr<AnaToolShare> result = getShare (name);
+      if (result != nullptr)
+	return result;
+      result.reset (val_share.release ());
+      m_shared[name] = result;
+      return result;
+    }
+
+
+
+    StatusCode AnaToolShareList ::
+    makeShare (const std::string& name,
+	       const AnaToolConfig& config,
+	       std::shared_ptr<AnaToolShare>& result)
+    {
+      using namespace msgToolHandle;
+
+      auto& share = m_shared[name];
+      auto res_result = share.lock();
+      if (res_result != nullptr)
+      {
+	result = res_result;
+	return StatusCode::SUCCESS;
+      }
+      ToolHandle<interfaceType_t> th;
+      AnaToolCleanup cleanup;
+      ANA_CHECK (config.makeTool (name, nullptr, th, cleanup));
+      res_result.reset (new AnaToolShare (th, cleanup));
+#ifndef ROOTCORE
+      if (!th.empty())
+      {
+	th->release ();
+      }
+#endif
+      assert (share.lock() == nullptr);
+      share = res_result;
+      result = res_result;
+      return StatusCode::SUCCESS;
+    }
+  }
+}
+
+//
+// legacy code
+//
+
 #ifdef ROOTCORE
 
 namespace asg
@@ -147,7 +240,7 @@ namespace asg
       auto tools = toolSvc->getTools();
       bool out(false);
       for(auto atool : tools) {
-         if(atool->name() == fullName) {out=true;tool=atool;break;}
+         if(atool && atool->name() == fullName) {out=true;tool=atool;break;}
       }
       toolSvc.release().ignore();
       return out;
@@ -189,11 +282,328 @@ namespace asg
       if(joSvc.release().isFailure()) return StatusCode::FAILURE;
       return StatusCode::SUCCESS;
    }
+  }
+}
+#endif
 
+namespace asg
+{
+  namespace detail
+  {
+    void AnaToolConfig ::
+    swap (AnaToolConfig& that) noexcept
+    {
+      m_type.swap (that.m_type);
+      m_factory.swap (that.m_factory);
+      m_properties.swap (that.m_properties);
+    }
+
+
+
+    bool AnaToolConfig ::
+    empty () const noexcept
+    {
+      if (!m_properties.empty())
+	return false;
+      if (!m_type.empty())
+	return false;
+#ifdef ROOTCORE
+      if (m_factory)
+	return false;
+#endif
+      return true;
+    }
+
+
+
+    const std::string& AnaToolConfig ::
+    type () const noexcept
+    {
+      return m_type;
+    }
+
+
+
+    void AnaToolConfig ::
+    setType (std::string type) noexcept
+    {
+      m_type = std::move (type);
+    }
 
+
+
+    void AnaToolConfig ::
+    addProperty (const std::string& name,
+		 const std::shared_ptr<AnaToolProperty>& property)
+    {
+      m_properties[name] = property;
+    }
+
+
+
+#ifdef ROOTCORE
+  StatusCode AnaToolConfig ::
+  allocateTool (AsgTool*& toolPtr, const std::string& toolName) const
+  {
+    using namespace msgToolHandle;
+
+    if (m_factory)
+    {
+      ANA_CHECK (m_factory (toolPtr, toolName));
+      return StatusCode::SUCCESS;
+    }
+
+    try
+    {
+      ANA_CHECK (detail::makeToolRootCore (type(), toolName, toolPtr));
+    } catch (std::exception& e)
+    {
+      ANA_MSG_ERROR ("encountered exception during tool creation(" <<
+		     type() << "," << toolName << "): " << e.what());
+      return StatusCode::FAILURE;
+    }
+    if (toolPtr == nullptr)
+    {
+      ANA_MSG_ERROR ("failed to allocate tool, this is typically caused either by the tool inheriting from AsgTool virtually or because its first base class is not AsgTool): " + type());
+      return StatusCode::FAILURE;
+    }
+    return StatusCode::SUCCESS;
   }
+#endif
 
 
-}
 
+#ifndef ROOTCORE
+    StatusCode AnaToolConfig ::
+    applyPropertiesAthena (const std::string& toolName,
+			   AnaToolCleanup& cleanup) const
+    {
+      using namespace msgToolHandle;
+
+      for (auto& property : m_properties)
+      {
+	ANA_CHECK (property.second->applyPropertyAthena
+		   (toolName, property.first, cleanup));
+      }
+      return StatusCode::SUCCESS;
+    }
+#endif
+
+
+
+    /*
+    namespace
+    {
+      /// convert the cleanup list into a single cleanup pointer
+      std::shared_ptr<void>
+      compressCleanup (std::list<std::shared_ptr<void> >& baseCleanup)
+      {
+	if (baseCleanup.empty())
+	  return std::shared_ptr<void> ();
+	if (baseCleanup.size() == 1)
+	  return baseCleanup.front();
+	return std::shared_ptr<std::vector<std::shared_ptr<void> > >
+	  (new std::vector<std::shared_ptr<void> > (baseCleanup.begin(),
+						    baseCleanup.end()));
+      }
+    }
+    */
+
+
+
+#ifdef ROOTCORE
+    StatusCode AnaToolConfig ::
+    makeToolRootCore (const std::string& toolName, IAsgTool*& toolPtr,
+		      AnaToolCleanup& cleanup) const
+    {
+      using namespace msgToolHandle;
+
+      asg::AsgTool *rawToolPtr = nullptr;
+      ANA_CHECK (allocateTool (rawToolPtr, toolName));
+      std::shared_ptr<AsgTool> sharedPtr (rawToolPtr);
+      AnaToolCleanup mycleanup;
+
+      for (auto& property : m_properties)
+      {
+	ANA_CHECK (property.second->applyPropertyRootCore
+		     (*rawToolPtr, property.first, mycleanup));
+      }
+      ANA_CHECK (rawToolPtr->initialize());
+
+      mycleanup.addCleanup (sharedPtr, false);
+      cleanup.swap (mycleanup);
+      toolPtr = sharedPtr.get();
+      return StatusCode::SUCCESS;
+    }
+#endif
+
+
+#ifndef ROOTCORE
+    /// \brief manage the reference count on a tool
+
+    struct ToolRefManager
+    {
+      ToolRefManager (const ToolHandle<IAlgTool>& val_tool, bool addRef)
+	: m_tool (val_tool), m_releases (m_tool->refCount())
+      {
+	if (addRef)
+	{
+	  m_tool->addRef();
+	  ++ m_releases;
+	}
+      }
+
+      ~ToolRefManager ()
+      {
+        using namespace msgToolHandle;
+        assert (m_releases <= m_tool->refCount());
+        if (m_releases > 0)
+        {
+          // for (unsigned iter = 1, end = m_tool->refCount(); iter != end; ++ iter)
+          for (unsigned iter = 1; iter != m_releases; ++ iter)
+            m_tool->release();
+          ANA_CHECK_THROW (m_tool.release());
+        }
+      }
+
+      ToolHandle<IAlgTool> m_tool;
+      unsigned m_releases = 0;
+    };
+
+
+
+    StatusCode AnaToolPropertyValueAthena ::
+    applyPropertyAthena (const std::string& toolName,
+			 const std::string& name,
+			 AnaToolCleanup& /*cleanup*/)
+      const
+    {
+      using namespace msgToolHandle;
+
+      // this is so we clear out properties from catalogue when tool
+      // is destroyed. DISABLED: we no longer clear out tools in Athena
+      // std::shared_ptr<PropertyValueManager> manager
+      //   (new PropertyValueManager (toolName, name));
+      // cleanup.addCleanup (manager);
+
+      // for athena we hand our property to the joboptions svc
+      ANA_CHECK (detail::addPropertyToCatalogue (toolName, name, m_value));
+      // manager->m_cleanup = true;
+      return StatusCode::SUCCESS;
+    }
 #endif
+
+
+
+    StatusCode AnaToolConfig ::
+    makeBaseTool (const std::string& name,
+                  parentType_t *parent,
+		  ToolHandle<interfaceType_t>& th,
+		  AnaToolCleanup& cleanup) const
+    {
+      using namespace msgToolHandle;
+
+      std::string toolName;
+      if (parent)
+        toolName = parent->name() + "." + name;
+      else
+        toolName = "ToolSvc." + name;
+
+#ifdef ROOTCORE
+      interfaceType_t *baseToolPtr = nullptr;
+      AnaToolCleanup baseCleanup;
+      ANA_CHECK (makeToolRootCore (toolName, baseToolPtr, baseCleanup));
+      th = ToolHandle<interfaceType_t> (baseToolPtr);
+      cleanup.swap (baseCleanup);
+#else
+      AnaToolCleanup baseCleanup;
+      ANA_CHECK (applyPropertiesAthena (toolName, baseCleanup));
+      ToolHandle<interfaceType_t> myth (m_type + "/" + name, parent);
+      ANA_CHECK (myth.retrieve());
+      // disabling this as it causes crashes in offline.  if you
+      // re-enable this, also reenable the cleanup tools in
+      // applyPropertiesAthena
+      // std::shared_ptr<detail::ToolRefManager> manager
+      //   (new detail::ToolRefManager (myth, true));
+      // baseCleanup.addCleanup (manager, false);
+      th = myth;
+      myth->release ();
+      cleanup.swap (baseCleanup);
+#endif
+      return StatusCode::SUCCESS;
+    }
+
+
+
+    void AnaToolCleanup ::
+    swap (AnaToolCleanup& that)
+    {
+      m_cleanup.swap (that.m_cleanup);
+    }
+
+
+
+    void AnaToolCleanup ::
+    addCleanup (AnaToolCleanup val_cleanup, bool post)
+    {
+      if (post)
+      {
+	for (auto& cleanup : val_cleanup.m_cleanup)
+	  m_cleanup.push_back (cleanup);
+      } else
+      {
+	val_cleanup.addCleanup (*this, true);
+	m_cleanup.swap (val_cleanup.m_cleanup);
+      }
+    }
+
+
+
+    void AnaToolCleanup ::
+    addCleanup (const std::shared_ptr<void>& val_cleanup,
+		bool post)
+    {
+      if (val_cleanup)
+      {
+	if (post)
+	  m_cleanup.push_back (val_cleanup);
+	else
+	  m_cleanup.push_front (val_cleanup);
+      }
+    }
+
+
+
+    StatusCode AnaToolConfig ::
+    setProperty (const std::string& val_name, const char *val_value)
+    {
+      return setProperty (val_name, std::string (val_value));
+    }
+
+
+
+#ifndef ROOTCORE
+    AnaToolPropertyCopyTool ::
+    AnaToolPropertyCopyTool (const std::string& val_type,
+                             const std::string& val_name)
+      : m_type (val_type), m_name (val_name)
+    {
+    }
+
+    StatusCode AnaToolPropertyCopyTool ::
+    applyPropertyAthena (const std::string& toolName,
+                         const std::string& name,
+                         AnaToolCleanup& /*cleanup*/)
+      const
+    {
+      using namespace msgToolHandle;
+
+      std::string myname = toolName + "." + name;
+
+      ANA_CHECK (addPropertyToCatalogue (toolName, name, m_type + "/" + name));
+      ANA_CHECK (copyPropertiesInCatalogue (m_name, myname));
+      return StatusCode::SUCCESS;
+    }
+#endif
+  }
+}
diff --git a/Control/AthToolSupport/AsgTools/Root/AsgMessaging.cxx b/Control/AthToolSupport/AsgTools/Root/AsgMessaging.cxx
index 6e84fdd8d909c52777337a5e6171c9b373d027d2..2ca7c479e09b9f4c482014bf7adf99dcafb1ad5c 100644
--- a/Control/AthToolSupport/AsgTools/Root/AsgMessaging.cxx
+++ b/Control/AthToolSupport/AsgTools/Root/AsgMessaging.cxx
@@ -1,4 +1,4 @@
-// $Id: AsgMessaging.cxx 615798 2014-09-09 16:02:17Z krasznaa $
+// $Id: AsgMessaging.cxx 784571 2016-11-16 14:27:23Z will $
 
 // Local include(s):
 #include "AsgTools/AsgMessaging.h"
@@ -15,7 +15,7 @@ namespace asg {
    AsgMessaging::AsgMessaging( const std::string& name )
       :
 #ifdef ASGTOOL_ATHENA
-      AthMessaging( Gaudi::svcLocator()->service< IMessageSvc >( "MessageSvc" ),
+     AthMessaging( Gaudi::svcLocator()->service< IMessageSvc >( "MessageSvc", false ),
                     name )
 #elif defined(ASGTOOL_STANDALONE)
       m_msg( name )
@@ -29,7 +29,7 @@ namespace asg {
    AsgMessaging::AsgMessaging( const IAsgTool* tool )
       :
 #ifdef ASGTOOL_ATHENA
-      AthMessaging( Gaudi::svcLocator()->service< IMessageSvc >( "MessageSvc" ),
+     AthMessaging( Gaudi::svcLocator()->service< IMessageSvc >( "MessageSvc", false ),
                     tool->name() )
 #elif defined(ASGTOOL_STANDALONE)
       m_msg( tool )
diff --git a/Control/AthToolSupport/AsgTools/Root/AsgMetadataTool.cxx b/Control/AthToolSupport/AsgTools/Root/AsgMetadataTool.cxx
index b7b3392bdf009494c7a52b9ec2d505fac9dc0ed9..6b6c3e0ba21476c0c121ab3bde793f33ce9ba6ac 100644
--- a/Control/AthToolSupport/AsgTools/Root/AsgMetadataTool.cxx
+++ b/Control/AthToolSupport/AsgTools/Root/AsgMetadataTool.cxx
@@ -1,4 +1,4 @@
-// $Id: AsgMetadataTool.cxx 692722 2015-09-02 13:06:02Z krasznaa $
+// $Id: AsgMetadataTool.cxx 771072 2016-08-31 14:50:22Z krasznaa $
 
 // System include(s):
 #include <stdexcept>
@@ -36,11 +36,12 @@ namespace asg {
       : AsgTool( name ),
 #ifdef ASGTOOL_STANDALONE
         m_inputMetaStore( SgTEventMeta::InputStore ),
-        m_outputMetaStore( SgTEventMeta::OutputStore )
+        m_outputMetaStore( SgTEventMeta::OutputStore ),
 #elif defined(ASGTOOL_ATHENA)
         m_inputMetaStore( "StoreGateSvc/InputMetaDataStore", name ),
-        m_outputMetaStore( "StoreGateSvc/MetaDataStore", name )
+        m_outputMetaStore( "StoreGateSvc/MetaDataStore", name ),
 #endif // Environment selection
+        m_beginInputFileCalled( false )
    {
 
 #ifdef ASGTOOL_STANDALONE
@@ -132,6 +133,7 @@ namespace asg {
 
       // Call the appropriate member function:
       if( inc.type() == IncidentType::BeginInputFile ) {
+         m_beginInputFileCalled = true;
          if( beginInputFile().isFailure() ) {
             ATH_MSG_FATAL( "Failed to call beginInputFile()" );
             throw std::runtime_error( "Couldn't call beginInputFile()" );
@@ -142,6 +144,16 @@ namespace asg {
             throw std::runtime_error( "Couldn't call endInputFile()" );
          }
       } else if( inc.type() == IncidentType::BeginEvent ) {
+         // If the tool didn't catch the begin input file incident for the
+         // first input file of the job, then call the appropriate function
+         // now.
+         if( ! m_beginInputFileCalled ) {
+            m_beginInputFileCalled = true;
+            if( beginInputFile().isFailure() ) {
+               ATH_MSG_FATAL( "Failed to call beginInputFile()" );
+               throw std::runtime_error( "Couldn't call beginInputFile()" );
+            }
+         }
          if( beginEvent().isFailure() ) {
             ATH_MSG_FATAL( "Failed to call beginEvent()" );
             throw std::runtime_error( "Couldn't call beginEvent()" );
diff --git a/Control/AthToolSupport/AsgTools/cmt/requirements b/Control/AthToolSupport/AsgTools/cmt/requirements
index 8c5de4a13e2e94c01efa959156864ddd03554b6a..f1f249dd5a01f2c2df90a6e2c746ddc259596ff3 100644
--- a/Control/AthToolSupport/AsgTools/cmt/requirements
+++ b/Control/AthToolSupport/AsgTools/cmt/requirements
@@ -1,5 +1,5 @@
 package AsgTools
-# $Id: requirements 745006 2016-05-05 10:40:32Z will $
+# $Id: requirements 790389 2016-12-18 13:39:12Z krumnack $
 
 author David Adams
 
@@ -7,6 +7,8 @@ public
 
 use AtlasPolicy      AtlasPolicy-*
 
+use  xAODRootAccess             xAODRootAccess-*                Control
+
 use GaudiInterface   GaudiInterface-*   External
 #use  AtlasGoogleTest                 AtlasGoogleTest-*                    External