From 18e0a296ff1e70d7b609067f65862ccc219fa48b Mon Sep 17 00:00:00 2001
From: Charles Leggett <charles.g.leggett@gmail.com>
Date: Tue, 20 Dec 2016 20:55:09 +0100
Subject: [PATCH] Property modernization w/ Gaudi v28
 (AthenaBaseComps-00-08-00)

	* updates for Property modernization. see gaudi/Gaudi!182
	* requires Gaudi v28
	* tag AthenaBaseComps-00-08-00

M       test/AthReentrantAlgorithm_test.cxx
M       test/propertyHandling_test.cxx
M       AthenaBaseComps/AthAlgTool.h
M       AthenaBaseComps/AthReentrantAlgorithm.h
M       AthenaBaseComps/AthAlgorithm.h

2016-12-07 Jack Cranshaw <cranshaw@anl.gov>
	* Tagging AthenaBaseComps-00-07-21
	* Add EventContext aware call to DecisionSvc

scott snyder  <snyder@bnl.gov>
2016-10-31  scott snyder  <snyder@bnl.gov>

	* Tagging AthenaBaseComps-00-07-20.
	* Get unordered_map from stdlib.

...
(Long ChangeLog diff - truncated)
---
 .../AthenaBaseComps/AthAlgTool.h              |  29 +-
 .../AthenaBaseComps/AthAlgorithm.h            |  27 +-
 .../AthenaBaseComps/AthCnvSvc.h               |   6 +-
 .../AthenaBaseComps/AthHistogramming.h        |  14 +-
 .../AthenaBaseComps/AthMessaging.h            |   2 +-
 .../AthenaBaseComps/AthReentrantAlgorithm.h   | 279 ++++++++++++++++--
 .../AthenaBaseComps/src/AthHistogramming.cxx  |  28 +-
 .../src/AthReentrantAlgorithm.cxx             | 111 ++++++-
 .../AthenaBaseComps/src/FilteredAlgorithm.cxx |   9 +-
 .../test/AthReentrantAlgorithm_test.cxx       |  17 +-
 .../test/propertyHandling_test.cxx            |  35 +--
 11 files changed, 427 insertions(+), 130 deletions(-)

diff --git a/Control/AthenaBaseComps/AthenaBaseComps/AthAlgTool.h b/Control/AthenaBaseComps/AthenaBaseComps/AthAlgTool.h
index fc3058362b7..f24e9d7981b 100644
--- a/Control/AthenaBaseComps/AthenaBaseComps/AthAlgTool.h
+++ b/Control/AthenaBaseComps/AthenaBaseComps/AthAlgTool.h
@@ -97,17 +97,10 @@ public:
                             SG::VarHandleKey& hndl,
                             const std::string& doc,
                             std::true_type,
-                            std::false_type) const
+                            std::false_type)
   {
-    AthAlgTool* aa = const_cast<AthAlgTool*>(this);
-    Gaudi::DataHandle::Mode mode = hndl.mode();
-    if (mode & Gaudi::DataHandle::Reader)
-      aa->declareInput(&hndl);
-    if (mode & Gaudi::DataHandle::Writer)
-      aa->declareOutput(&hndl);
-#ifdef ATHENAHIVE
-    hndl.setOwner(aa);
-#endif
+    this->declare(hndl);
+    hndl.setOwner(this);
 
     return AlgTool::declareProperty(name,hndl,doc);
   }
@@ -118,16 +111,14 @@ public:
                             SG::VarHandleKeyArray& hndArr,
                             const std::string& doc,
                             std::false_type,
-                            std::true_type) const
+                            std::true_type)
   {
 
-    AthAlgTool* aa = const_cast<AthAlgTool*>(this);
-
     m_vhka.push_back(&hndArr);
 
     Property* p =  AlgTool::declareProperty(name, hndArr, doc);
     if (p != 0) {
-      p->declareUpdateHandler(&AthAlgTool::updateVHKA, aa);
+      p->declareUpdateHandler(&AthAlgTool::updateVHKA, this);
     } else {
       ATH_MSG_ERROR("unable to call declareProperty on VarHandleKeyArray " 
                     << name);
@@ -148,13 +139,9 @@ public:
     // debug() << "updateVHKA for property " << p.name() << " " << p.toString() 
     //         << "  size: " << m_vhka.size() << endmsg;
     for (auto &a : m_vhka) {
-      Gaudi::DataHandle::Mode mode = a->mode();
       std::vector<SG::VarHandleKey*> keys = a->keys();
       for (auto k : keys) {
-        if (mode & Gaudi::DataHandle::Reader)
-          this->declareInput(k);
-        if (mode & Gaudi::DataHandle::Writer)
-          this->declareOutput(k);
+        this->declare(*k);
         k->setOwner(this);
       }
     }
@@ -177,7 +164,7 @@ public:
                             T& property,
                             const std::string& doc,
                             std::false_type,
-                            std::false_type) const
+                            std::false_type)
   {
     return AlgTool::declareProperty(name, property, doc);
   }
@@ -196,7 +183,7 @@ public:
   template <class T>
   Property* declareProperty(const std::string& name,
                             T& property,
-                            const std::string& doc="none") const
+                            const std::string& doc="none")
   {
     return declareProperty (name, property, doc,
                             std::is_base_of<SG::VarHandleKey, T>(),
diff --git a/Control/AthenaBaseComps/AthenaBaseComps/AthAlgorithm.h b/Control/AthenaBaseComps/AthenaBaseComps/AthAlgorithm.h
index d45912f7e86..2dc0c174d16 100644
--- a/Control/AthenaBaseComps/AthenaBaseComps/AthAlgorithm.h
+++ b/Control/AthenaBaseComps/AthenaBaseComps/AthAlgorithm.h
@@ -126,15 +126,10 @@ public:
                             SG::VarHandleKey& hndl,
                             const std::string& doc,
                             std::true_type,
-                            std::false_type) const
+                            std::false_type)
   {
-    AthAlgorithm* aa = const_cast<AthAlgorithm*>(this);
-    Gaudi::DataHandle::Mode mode = hndl.mode();
-    if (mode & Gaudi::DataHandle::Reader)
-      aa->declareInput(&hndl);
-    if (mode & Gaudi::DataHandle::Writer)
-      aa->declareOutput(&hndl);
-    hndl.setOwner(aa);
+    this->declare(hndl);
+    hndl.setOwner(this);
 
     return Algorithm::declareProperty(name,hndl,doc);
   }
@@ -145,7 +140,7 @@ public:
                             SG::VarHandleKeyArray& hndArr,
                             const std::string& doc,
                             std::false_type,
-                            std::true_type) const
+                            std::true_type)
   {
 
     // std::ostringstream ost;
@@ -156,13 +151,11 @@ public:
     //     << "\n";
     // debug() << ost.str() << endmsg;
 
-    AthAlgorithm* aa = const_cast<AthAlgorithm*>(this);
-
     m_vhka.push_back(&hndArr);
 
     Property* p =  Algorithm::declareProperty(name, hndArr, doc);
     if (p != 0) {
-      p->declareUpdateHandler(&AthAlgorithm::updateVHKA, aa);
+      p->declareUpdateHandler(&AthAlgorithm::updateVHKA, this);
     } else {
       ATH_MSG_ERROR("unable to call declareProperty on VarHandleKeyArray " 
                     << name);
@@ -184,13 +177,9 @@ public:
     // debug() << "updateVHKA for property " << p.name() << " " << p.toString() 
     //         << "  size: " << m_vhka.size() << endmsg;
     for (auto &a : m_vhka) {
-      Gaudi::DataHandle::Mode mode = a->mode();
       std::vector<SG::VarHandleKey*> keys = a->keys();
       for (auto k : keys) {
-        if (mode & Gaudi::DataHandle::Reader)
-          this->declareInput(k);
-        if (mode & Gaudi::DataHandle::Writer)
-          this->declareOutput(k);
+        this->declare(*k);
         k->setOwner(this);
       }
     }
@@ -215,7 +204,7 @@ public:
                             const std::string& doc,
                             std::false_type,
                             std::false_type
-                            ) const
+                            ) 
   {
     return Algorithm::declareProperty(name, property, doc);
   }
@@ -234,7 +223,7 @@ public:
   template <class T>
   Property* declareProperty(const std::string& name,
                             T& property,
-                            const std::string& doc="none") const
+                            const std::string& doc="none") 
   {
 
     return declareProperty (name, property, doc,
diff --git a/Control/AthenaBaseComps/AthenaBaseComps/AthCnvSvc.h b/Control/AthenaBaseComps/AthenaBaseComps/AthCnvSvc.h
index 301c8f564d5..065828bcd77 100644
--- a/Control/AthenaBaseComps/AthenaBaseComps/AthCnvSvc.h
+++ b/Control/AthenaBaseComps/AthenaBaseComps/AthCnvSvc.h
@@ -13,9 +13,7 @@
 
 // STL includes
 #include <string>
-
-// CxxUtils includes
-#include "CxxUtils/unordered_map.h" // move to STL when available
+#include <unordered_map>
 
 // GaudiKernel
 #include "GaudiKernel/IConversionSvc.h"
@@ -104,7 +102,7 @@ public:
       return this->clID() < rhs.clID();
     }
   };
-  typedef SG::unordered_map<CLID,WorkerEntry> Workers;
+  typedef std::unordered_map<CLID,WorkerEntry> Workers;
 
   /////////////////////////////////////////////////////////////////// 
   // Public methods: 
diff --git a/Control/AthenaBaseComps/AthenaBaseComps/AthHistogramming.h b/Control/AthenaBaseComps/AthenaBaseComps/AthHistogramming.h
index 3f8150f464b..b8be7443dd2 100644
--- a/Control/AthenaBaseComps/AthenaBaseComps/AthHistogramming.h
+++ b/Control/AthenaBaseComps/AthenaBaseComps/AthHistogramming.h
@@ -228,7 +228,7 @@ inline TH1* AthHistogramming::bookGetPointer( const TH1& hist, const std::string
   // We need to create a non-const clone
   TH1* histClone = dynamic_cast< TH1* >( hist.Clone() );
   if ( !histClone ) {
-    m_msg << MSG::ERROR << "Couldn't create a TH1 clone in bookGetPointer" << endreq;
+    m_msg << MSG::ERROR << "Couldn't create a TH1 clone in bookGetPointer" << endmsg;
     return 0;
   }
   return this->bookGetPointer( *histClone, tDir, stream );
@@ -238,7 +238,7 @@ inline TH1* AthHistogramming::bookGetPointer( const TH1& hist, const std::string
 inline TH1* AthHistogramming::bookGetPointer( TH1* hist, const std::string& tDir, const std::string& stream )
 {
   if ( !hist ) {
-    m_msg << MSG::ERROR << "Got a zero pointer to a TH1 in bookGetPointer" << endreq;
+    m_msg << MSG::ERROR << "Got a zero pointer to a TH1 in bookGetPointer" << endmsg;
     return 0;
   }
   return this->bookGetPointer( *hist, tDir, stream );
@@ -250,7 +250,7 @@ inline StatusCode AthHistogramming::book( const TH1& hist, const std::string& tD
   // We need to create a non-const clone
   TH1* histClone = dynamic_cast< TH1* >( hist.Clone() );
   if ( !histClone ) {
-    m_msg << MSG::ERROR << "Couldn't create a TH1 clone" << endreq;
+    m_msg << MSG::ERROR << "Couldn't create a TH1 clone" << endmsg;
     return StatusCode::FAILURE;
   }
   return this->book( *histClone, tDir, stream );
@@ -259,7 +259,7 @@ inline StatusCode AthHistogramming::book( const TH1& hist, const std::string& tD
 inline StatusCode AthHistogramming::book( TH1* hist, const std::string& tDir, const std::string& stream )
 {
   if ( !hist ) {
-    m_msg << MSG::ERROR << "Got a zero pointer to a TH1" << endreq;
+    m_msg << MSG::ERROR << "Got a zero pointer to a TH1" << endmsg;
     return StatusCode::FAILURE;
   }
   return this->book( *hist, tDir, stream );
@@ -271,7 +271,7 @@ inline StatusCode AthHistogramming::book( TH1& histRef, const std::string& tDir,
   // Call the other Book method and see if it returns a valid pointer
   TH1* histPointer = this->bookGetPointer( histRef, tDir, stream );
   if ( !histPointer ) {
-    m_msg << MSG::ERROR << "Couldn't book a TH1" << endreq;
+    m_msg << MSG::ERROR << "Couldn't book a TH1" << endmsg;
     return StatusCode::FAILURE;
   }
   return StatusCode::SUCCESS;
@@ -287,7 +287,7 @@ inline TH2* AthHistogramming::hist2d( const std::string& histName, const std::st
     {
       m_msg << MSG::ERROR
             << "Cannot get a 2-d histogram with name " << histName
-            << "... will probably seg-fault!" << endreq;
+            << "... will probably seg-fault!" << endmsg;
       return NULL;
     }
   // If the TH1 pointer is valid, simply return the dynamic_cast
@@ -304,7 +304,7 @@ inline TH3* AthHistogramming::hist3d( const std::string& histName, const std::st
     {
       m_msg << MSG::ERROR
             << "Cannot get a 3-d histogram with name " << histName
-            << "... will probably seg-fault!" << endreq;
+            << "... will probably seg-fault!" << endmsg;
       return NULL;
     }
   // If the TH1 pointer is valid, simply return the dynamic_cast
diff --git a/Control/AthenaBaseComps/AthenaBaseComps/AthMessaging.h b/Control/AthenaBaseComps/AthenaBaseComps/AthMessaging.h
index b01437ff993..7d5fb1072eb 100644
--- a/Control/AthenaBaseComps/AthenaBaseComps/AthMessaging.h
+++ b/Control/AthenaBaseComps/AthenaBaseComps/AthMessaging.h
@@ -27,7 +27,7 @@
  *  One usually inherits from this class and use it like so:
  *  @code
  *   void some_method (AthMessaging& o) 
- *   { o.msg() << "foo" << endreq; }
+ *   { o.msg() << "foo" << endmsg; }
  *  @endcode
  */
 
diff --git a/Control/AthenaBaseComps/AthenaBaseComps/AthReentrantAlgorithm.h b/Control/AthenaBaseComps/AthenaBaseComps/AthReentrantAlgorithm.h
index 152f4eab1a3..e9474333d13 100644
--- a/Control/AthenaBaseComps/AthenaBaseComps/AthReentrantAlgorithm.h
+++ b/Control/AthenaBaseComps/AthenaBaseComps/AthReentrantAlgorithm.h
@@ -1,25 +1,42 @@
-// This file's extension implies that it's C, but it's really -*- C++ -*-.
+///////////////////////// -*- C++ -*- /////////////////////////////
 
 /*
   Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
 */
 
-// $Id$
-/**
- * @file AthenaBaseComps/AthReentrantAlgorithm.h
- * @author scott snyder <snyder@bnl.gov>
- * @date Jan, 2016
- * @brief An algorithm that can be simultaneously executed in multiple threads.
- */
-
-
+// AthAlgorithm.h 
+// Header file for class AthReentrantAlgorithm
+// Author: Charles Leggett
+/////////////////////////////////////////////////////////////////// 
 #ifndef ATHENABASECOMPS_ATHREENTRANTALGORITHM_H
-#define ATHENABASECOMPS_ATHREENTRANTALGORITHM_H
+#define ATHENABASECOMPS_ATHREENTRANTALGORITHM_H 1
 
 
-#include "AthenaBaseComps/AthAlgorithm.h"
-#include "GaudiKernel/EventContext.h"
+// STL includes
+#include <string>
+#include <type_traits>
 
+// FrameWork includes
+#ifndef REENTRANT_GAUDI
+ #define ReEntAlgorithm Algorithm
+ #include "GaudiKernel/Algorithm.h"
+#else
+ #include "GaudiKernel/ReEntAlgorithm.h"
+#endif
+
+#include "GaudiKernel/MsgStream.h"
+#include "GaudiKernel/ServiceHandle.h"
+#include "AthenaBaseComps/AthCheckMacros.h"
+#include "AthenaBaseComps/AthMemMacros.h"
+#include "AthenaBaseComps/AthMessaging.h"
+#include "AthenaBaseComps/AthMsgStreamMacros.h"
+#include "StoreGate/StoreGateSvc.h"
+#include "StoreGate/VarHandleProperty.h"
+#include "StoreGate/VarHandleKeyProperty.h"
+#include "StoreGate/VarHandleKeyArrayProperty.h"
+#include "StoreGate/VarHandleKey.h"
+#include "StoreGate/VarHandleKeyArray.h"
+#include "AthenaKernel/IUserDataSvc.h"
 
 /**
  * @brief An algorithm that can be simultaneously executed in multiple threads.
@@ -64,7 +81,7 @@
  *    return StatusCode::SUCCESS;
  *  }
  *
- *  StatusCode MyAlg::execute_r (const EventContext& ctx)
+ *  StatusCode MyAlg::execute_r (const EventContext& ctx) const
  *  {
  *    SG::ReadHandle<MyObj> myobj (m_rhandle, ctx);
  *    const MyObj& p = *myobj;
@@ -72,14 +89,56 @@
  *  }
  @endcode
  */
+
+
 class AthReentrantAlgorithm
-  : public AthAlgorithm
-{
-public:
-  /// Use constructor from base class.
-  using AthAlgorithm::AthAlgorithm;
+  : public ::ReEntAlgorithm,
+    public ::AthMessaging
+{ 
+  /////////////////////////////////////////////////////////////////// 
+  // Public methods: 
+  /////////////////////////////////////////////////////////////////// 
+ public: 
 
+  // fwd compat w/ gaudi-21
+  using AthMessaging::msg;
+
+  // Copy constructor: 
+
+  /// Constructor with parameters: 
+  AthReentrantAlgorithm(const std::string& name, 
+               ISvcLocator* pSvcLocator,
+               const std::string& version=PACKAGE_VERSION);
+
+  /// Destructor: 
+  virtual ~AthReentrantAlgorithm() override; 
+
+  /////////////////////////////////////////////////////////////////// 
+  // Const methods: 
+  ///////////////////////////////////////////////////////////////////
+
+  /** @brief The standard @c StoreGateSvc
+   * Returns (kind of) a pointer to the @c StoreGateSvc
+   * @WARNING: deprecated. please use @c evtStore() instead
+   */
+  ServiceHandle<StoreGateSvc>& sgSvc() const;
+
+  /** @brief The standard @c StoreGateSvc (event store)
+   * Returns (kind of) a pointer to the @c StoreGateSvc
+   */
+  ServiceHandle<StoreGateSvc>& evtStore() const;
 
+  /** @brief The standard @c StoreGateSvc/DetectorStore
+   * Returns (kind of) a pointer to the @c StoreGateSvc
+   */
+  ServiceHandle<StoreGateSvc>& detStore() const;
+
+  /** @brief The standard @c UserDataSvc 
+   * Returns (kind of) a pointer to the @c UserDataSvc
+   */
+  ServiceHandle<IUserDataSvc>& userStore() const;
+
+#ifndef REENTRANT_GAUDI
   /**
    * @brief Standard Gaudi execute method.
    *
@@ -96,7 +155,185 @@ public:
    * Override this for your algorithm.
    */
   virtual StatusCode execute_r (const EventContext& ctx) const = 0;
-};
+#endif
+
+
+private:
+  // to keep track of VarHandleKeyArrays for data dep registration
+  mutable std::vector<SG::VarHandleKeyArray*> m_vhka;
+
+  /////////////////////////////////////////////////////////////////
+  //
+  //// For automatic registration of Handle data products
+  //
+
+public:
+  /**
+   * @brief Declare a new Gaudi property.
+   * @param name Name of the property.
+   * @param property Object holding the property value.
+   * @param doc Documenation string for the property.
+   *
+   * This is the version for types that derive from @c SG::VarHandleKey.
+   * The property value object is put on the input and output lists as
+   * appropriate; then we forward to the base class.
+   */
+  Property* declareProperty(const std::string& name,
+                            SG::VarHandleKey& hndl,
+                            const std::string& doc,
+                            std::true_type,
+                            std::false_type)
+  {
+    this->declare(hndl);
+    hndl.setOwner(this);
+
+    return Algorithm::declareProperty(name,hndl,doc);
+  }
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+  Property* declareProperty(const std::string& name,
+                            SG::VarHandleKeyArray& hndArr,
+                            const std::string& doc,
+                            std::false_type,
+                            std::true_type)
+  {
+
+    m_vhka.push_back(&hndArr);
+
+    Property* p =  Algorithm::declareProperty(name, hndArr, doc);
+    if (p != 0) {
+      p->declareUpdateHandler(&AthReentrantAlgorithm::updateVHKA, this);
+    } else {
+      ATH_MSG_ERROR("unable to call declareProperty on VarHandleKeyArray " 
+                    << name);
+    }
+
+    return p;
+
+  }
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+  // since the contents of the VarHandleKeyArrays have not been read 
+  // in from the configurables by the time that declareProperty is
+  // executed, we must cache them and loop through them later to
+  // register the data dependencies
+
+  void updateVHKA(Property& /*p*/) {
+    // debug() << "updateVHKA for property " << p.name() << " " << p.toString() 
+    //         << "  size: " << m_vhka.size() << endmsg;
+    for (auto &a : m_vhka) {
+      std::vector<SG::VarHandleKey*> keys = a->keys();
+      for (auto k : keys) {
+        this->declare(*k);
+        k->setOwner(this);
+      }
+    }
+  }
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+
+  /**
+   * @brief Declare a new Gaudi property.
+   * @param name Name of the property.
+   * @param property Object holding the property value.
+   * @param doc Documenation string for the property.
+   *
+   * This is the generic version, for types that do not derive
+   * from  @c SG::VarHandleKey.  It just forwards to the base class version
+   * of @c declareProperty.
+   */
+  template <class T>
+  Property* declareProperty(const std::string& name,
+                            T& property,
+                            const std::string& doc,
+                            std::false_type,
+                            std::false_type
+                            ) 
+  {
+    return Algorithm::declareProperty(name, property, doc);
+  }
+
+
+  /**
+   * @brief Declare a new Gaudi property.
+   * @param name Name of the property.
+   * @param property Object holding the property value.
+   * @param doc Documenation string for the property.
+   *
+   * This dispatches to either the generic @c declareProperty or the one
+   * for VarHandle/Key, depending on whether or not @c property
+   * derives from @c SG::VarHandleKey or @c SG::VarHandleKeyArray.
+   */
+  template <class T>
+  Property* declareProperty(const std::string& name,
+                            T& property,
+                            const std::string& doc="none")
+  {
+
+    return declareProperty (name, property, doc,
+                            std::is_base_of<SG::VarHandleKey, T>(),
+                            std::is_base_of<SG::VarHandleKeyArray,T>()
+    );
+
+  }
+
+  
+  /////////////////////////////////////////////////////////////////// 
+  // Non-const methods: 
+  /////////////////////////////////////////////////////////////////// 
+
+  /////////////////////////////////////////////////////////////////// 
+  // Protected methods: 
+  /////////////////////////////////////////////////////////////////// 
+ protected: 
+
+  /// callback for output level property 
+  void msg_update_handler(Property& outputLevel);
+
+  /////////////////////////////////////////////////////////////////// 
+  // Private data: 
+  /////////////////////////////////////////////////////////////////// 
+ private: 
+
+  /// Default constructor: 
+  AthReentrantAlgorithm(); //> not implemented
+  AthReentrantAlgorithm (const AthReentrantAlgorithm& ); //> not implemented
+  AthReentrantAlgorithm& operator= (const AthReentrantAlgorithm&); //> not implemented
+
+  typedef ServiceHandle<StoreGateSvc> StoreGateSvc_t;
+  /// Pointer to StoreGate (event store by default)
+  mutable StoreGateSvc_t m_evtStore;
+
+  /// Pointer to StoreGate (detector store by default)
+  mutable StoreGateSvc_t m_detStore;
+
+  typedef ServiceHandle<IUserDataSvc> UserDataSvc_t;
+  /// Pointer to IUserDataSvc
+  mutable UserDataSvc_t m_userStore;
+}; 
+
+/////////////////////////////////////////////////////////////////// 
+// Inline methods: 
+/////////////////////////////////////////////////////////////////// 
+
+inline
+ServiceHandle<StoreGateSvc>& AthReentrantAlgorithm::sgSvc() const 
+{ return m_evtStore; }
+
+inline
+ServiceHandle<StoreGateSvc>& AthReentrantAlgorithm::evtStore() const 
+{ return m_evtStore; }
+
+inline
+ServiceHandle<StoreGateSvc>& AthReentrantAlgorithm::detStore() const 
+{ return m_detStore; }
 
+inline
+ServiceHandle<IUserDataSvc>& AthReentrantAlgorithm::userStore() const 
+{ return m_userStore; }
 
-#endif // not ATHENABASECOMPS_ATHREENTRANTALGORITHM_H
+#endif //> !ATHENABASECOMPS_ATHREENTRANTALGORITHM_H
diff --git a/Control/AthenaBaseComps/src/AthHistogramming.cxx b/Control/AthenaBaseComps/src/AthHistogramming.cxx
index 6a0d50b499b..66bd18656ab 100644
--- a/Control/AthenaBaseComps/src/AthHistogramming.cxx
+++ b/Control/AthenaBaseComps/src/AthHistogramming.cxx
@@ -53,7 +53,7 @@ AthHistogramming::AthHistogramming( const std::string& name ) :
 AthHistogramming::~AthHistogramming()
 {
   //ATH_MSG_DEBUG ("Calling destructor of AthHistogramming");
-  if ( m_msg.level() <= MSG::VERBOSE ) m_msg << MSG::DEBUG << "Calling destructor of AthHistogramming" << endreq;
+  if ( m_msg.level() <= MSG::VERBOSE ) m_msg << MSG::DEBUG << "Calling destructor of AthHistogramming" << endmsg;
 }
 
 
@@ -113,7 +113,7 @@ TH1* AthHistogramming::bookGetPointer( TH1& histRef, std::string tDir, std::stri
       m_msg << MSG::WARNING
             << "Detected a hash collission. The hash for the histogram with name=" << histName
             << " already exists and points to a histogram with name=" << it->second->GetName()
-            << " NOT going to book the new histogram and returning a NULL pointer!" << endreq;
+            << " NOT going to book the new histogram and returning a NULL pointer!" << endmsg;
       return NULL;
     }
 
@@ -131,7 +131,7 @@ TH1* AthHistogramming::bookGetPointer( TH1& histRef, std::string tDir, std::stri
             << ", title " << histTitle
             << ", tile prefix " << m_histTitlePrefix
             << ", and tile postfix " << m_histTitlePostfix
-            << " in " << m_name << "!" << endreq;
+            << " in " << m_name << "!" << endmsg;
       return NULL;
     }
 
@@ -179,7 +179,7 @@ TH1* AthHistogramming::hist( const std::string& histName, const std::string& tDi
                     << m_histNamePrefix + histNameCopy + m_histNamePostfix
                     << " or with name " << histNameCopy
                     << " in " << m_name << "... it doesn't exist, neither in the cached map nor in the THistSvc!"
-                    << " Will return an NULL pointer... you have to handle it correctly!" << endreq;
+                    << " Will return an NULL pointer... you have to handle it correctly!" << endmsg;
               return NULL;
             }
           // If we get to here, we actually found the histogram in the THistSvc.
@@ -219,7 +219,7 @@ TTree* AthHistogramming::bookGetPointer( const TTree& treeRef, std::string tDir,
     {
       m_msg << MSG::WARNING
             << "We got an invalid TTree pointer in the BookGetPointer(TTree*) method of the class" << m_name
-            << "!" << endreq;
+            << "!" << endmsg;
       return NULL;
     }
 
@@ -235,7 +235,7 @@ TTree* AthHistogramming::bookGetPointer( const TTree& treeRef, std::string tDir,
       m_msg << MSG::WARNING
             << "Detected a hash collission. The hash for the TTree with name=" << treeName
             << " already exists and points to a TTree with name=" << it->second->GetName()
-            << " NOT going to book the new histogram and returning a NULL pointer!" << endreq;
+            << " NOT going to book the new histogram and returning a NULL pointer!" << endmsg;
       return NULL;
     }
 
@@ -248,7 +248,7 @@ TTree* AthHistogramming::bookGetPointer( const TTree& treeRef, std::string tDir,
     {
       m_msg << MSG::WARNING
             << "We couldn't clone the TTree in the BookGetPointer(TTree&) method of the class" << m_name
-            << "!" << endreq;
+            << "!" << endmsg;
       return NULL;
     }
 
@@ -262,7 +262,7 @@ TTree* AthHistogramming::bookGetPointer( const TTree& treeRef, std::string tDir,
       m_msg << MSG::WARNING
             << "Problem registering TTree with name " << treeName
             << ", title " << treeTitle
-            << " in " << m_name << "!" << endreq;
+            << " in " << m_name << "!" << endmsg;
       return NULL;
     }
 
@@ -302,7 +302,7 @@ TTree* AthHistogramming::tree( const std::string& treeName, const std::string& t
           m_msg << MSG::WARNING
                 << "Problem retrieving the TTree with name " << treeNameCopy
                 << " in " << m_name << "... it doesn't exist, neither in the cached map nor in the THistSvc!"
-                << " Will return an NULL pointer... you have to handle it correctly!" << endreq;
+                << " Will return an NULL pointer... you have to handle it correctly!" << endmsg;
           return NULL;
         }
       // If we get to here, we actually found the TTree in the THistSvc.
@@ -336,7 +336,7 @@ TGraph* AthHistogramming::bookGetPointer( const TGraph& graphRef, std::string tD
     {
       m_msg << MSG::WARNING
             << "We got an invalid TGraph pointer in the BookGetPointer(TGraph*) method of the class" << m_name
-            << "!" << endreq;
+            << "!" << endmsg;
       return NULL;
     }
 
@@ -352,7 +352,7 @@ TGraph* AthHistogramming::bookGetPointer( const TGraph& graphRef, std::string tD
       m_msg << MSG::WARNING
             << "Detected a hash collission. The hash for the TGraph with name=" << graphName
             << " already exists and points to a TGraph with name=" << it->second->GetName()
-            << " NOT going to book the new histogram and returning a NULL pointer!" << endreq;
+            << " NOT going to book the new histogram and returning a NULL pointer!" << endmsg;
       return NULL;
     }
 
@@ -366,7 +366,7 @@ TGraph* AthHistogramming::bookGetPointer( const TGraph& graphRef, std::string tD
     {
       m_msg << MSG::WARNING
             << "We couldn't clone the TGraph in the BookGetPointer(TGraph&) method of the class" << m_name
-            << "!" << endreq;
+            << "!" << endmsg;
       return NULL;
     }
 
@@ -380,7 +380,7 @@ TGraph* AthHistogramming::bookGetPointer( const TGraph& graphRef, std::string tD
       m_msg << MSG::WARNING
             << "Problem registering TGraph with name " << graphName
             << ", title " << graphTitle
-            << " in " << m_name << "!" << endreq;
+            << " in " << m_name << "!" << endmsg;
       return NULL;
     }
 
@@ -427,7 +427,7 @@ TGraph* AthHistogramming::graph( const std::string& graphName, const std::string
                     << m_histNamePrefix + graphNameCopy + m_histNamePostfix
                     << " or with name " << graphNameCopy
                     << " in " << m_name << "... it doesn't exist, neither in the cached map nor in the THistSvc!"
-                    << " Will return an NULL pointer... you have to handle it correctly!" << endreq;
+                    << " Will return an NULL pointer... you have to handle it correctly!" << endmsg;
               return NULL;
             }
           // If we get to here, we actually found the TGraph in the THistSvc.
diff --git a/Control/AthenaBaseComps/src/AthReentrantAlgorithm.cxx b/Control/AthenaBaseComps/src/AthReentrantAlgorithm.cxx
index b7057e5027a..bc09e1db6f4 100644
--- a/Control/AthenaBaseComps/src/AthReentrantAlgorithm.cxx
+++ b/Control/AthenaBaseComps/src/AthReentrantAlgorithm.cxx
@@ -1,20 +1,114 @@
+///////////////////////// -*- C++ -*- /////////////////////////////
+
 /*
   Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
 */
 
-// $Id$
-/**
- * @file AthenaBaseComps/src/AthReentrantAlgorithm.cxx
- * @author scott snyder <snyder@bnl.gov>
- * @date Jan, 2016
- * @brief An algorithm that can be simultaneously executed in multiple threads.
- */
-
+// AthReentrantAlgorithm.cxx 
+// Implementation file for class AthReentrantAlgorithm
+// Author: C. Leggett
+/////////////////////////////////////////////////////////////////// 
 
+// AthenaBaseComps includes
 #include "AthenaBaseComps/AthReentrantAlgorithm.h"
+
+// FrameWork includes
+#include "GaudiKernel/Property.h"
+#ifndef REENTRANT_GAUDI
 #include "GaudiKernel/ThreadLocalContext.h"
+#endif
+
+/////////////////////////////////////////////////////////////////// 
+// Public methods: 
+/////////////////////////////////////////////////////////////////// 
+
+// Constructors
+////////////////
+AthReentrantAlgorithm::AthReentrantAlgorithm( const std::string& name, 
+			    ISvcLocator* pSvcLocator,
+			    const std::string& version ) : 
+  ::ReEntAlgorithm   ( name, pSvcLocator, version ),
+  ::AthMessaging( msgSvc(), name ),
+  m_evtStore    ( "StoreGateSvc/StoreGateSvc",  name ),
+  m_detStore    ( "StoreGateSvc/DetectorStore", name ),
+  m_userStore   ( "UserDataSvc/UserDataSvc", name )
+{
+  //
+  // Property declaration
+  // 
+  //declareProperty( "Property", m_nProperty );
+
+  auto props = getProperties();
+  for( Property* prop : props ) {
+    if( prop->name() != "OutputLevel" ) {
+      continue;
+    }
+    prop->declareUpdateHandler
+      (&AthReentrantAlgorithm::msg_update_handler, this);
+    break;
+  }
+
+  declareProperty( "EvtStore",
+                   m_evtStore = StoreGateSvc_t ("StoreGateSvc", name),
+                   "Handle to a StoreGateSvc instance: it will be used to "
+                   "retrieve data during the course of the job" );
+
+  declareProperty( "DetStore",
+                   m_detStore = StoreGateSvc_t ("StoreGateSvc/DetectorStore", name),
+                   "Handle to a StoreGateSvc/DetectorStore instance: it will be used to "
+                   "retrieve data during the course of the job" );
+
+  declareProperty( "UserStore",
+                   m_userStore = UserDataSvc_t ("UserDataSvc/UserDataSvc", name),
+                   "Handle to a UserDataSvc/UserDataSvc instance: it will be used to "
+                   "retrieve user data during the course of the job" );
+}
+
+// Destructor
+///////////////
+AthReentrantAlgorithm::~AthReentrantAlgorithm()
+{ 
+  ATH_MSG_DEBUG ("Calling destructor");
+}
+
+/////////////////////////////////////////////////////////////////// 
+// Const methods: 
+///////////////////////////////////////////////////////////////////
+
+/////////////////////////////////////////////////////////////////// 
+// Non-const methods: 
+/////////////////////////////////////////////////////////////////// 
+
+/////////////////////////////////////////////////////////////////// 
+// Protected methods: 
+/////////////////////////////////////////////////////////////////// 
+
+/////////////////////////////////////////////////////////////////// 
+// Const methods: 
+///////////////////////////////////////////////////////////////////
+
+/////////////////////////////////////////////////////////////////// 
+// Non-const methods: 
+/////////////////////////////////////////////////////////////////// 
+
+void 
+AthReentrantAlgorithm::msg_update_handler( Property& outputLevel ) 
+{
+   // We can't just rely on the return value of msgLevel() here. Since it's
+   // not well defined whether the base class gets updated with the new
+   // output level first, or this class. So by default just use the property
+   // itself. The fallback is only there in case Gaudi changes its property
+   // type at one point, to be able to fall back on something.
+   IntegerProperty* iprop = dynamic_cast< IntegerProperty* >( &outputLevel );
+   if( iprop ) {
+      msg().setLevel( iprop->value() );
+   } else {
+      msg().setLevel( msgLevel() );
+   }
+}
 
 
+#ifndef REENTRANT_GAUDI
 /**
  * @brief Standard Gaudi execute method.
  *
@@ -24,3 +118,4 @@ StatusCode AthReentrantAlgorithm::execute()
 {
   return execute_r (Gaudi::Hive::currentContext());
 }
+#endif
diff --git a/Control/AthenaBaseComps/src/FilteredAlgorithm.cxx b/Control/AthenaBaseComps/src/FilteredAlgorithm.cxx
index 5f5032b7d8a..27a386284fa 100644
--- a/Control/AthenaBaseComps/src/FilteredAlgorithm.cxx
+++ b/Control/AthenaBaseComps/src/FilteredAlgorithm.cxx
@@ -129,7 +129,14 @@ bool
 FilteredAlgorithm::isEventAccepted( ) const
 {
   bool result = true;
-  result = m_decSvc->isEventAccepted(this->name());
+  if (this->getContext()!=nullptr) {
+    result = m_decSvc->isEventAccepted(this->name(),*(this->getContext()));
+    //ATH_MSG_DEBUG("res=" << result << " n=" << this->name() << " sl=" << this->getContext()->slot() << " evt=" << this->getContext()->eventID().event_number());
+  } else {
+    ATH_MSG_DEBUG("Not a threaded app");
+    result = m_decSvc->isEventAccepted(this->name());
+  }
+
   return result;
 }
 
diff --git a/Control/AthenaBaseComps/test/AthReentrantAlgorithm_test.cxx b/Control/AthenaBaseComps/test/AthReentrantAlgorithm_test.cxx
index 0f1d285b969..cd7b44358a4 100644
--- a/Control/AthenaBaseComps/test/AthReentrantAlgorithm_test.cxx
+++ b/Control/AthenaBaseComps/test/AthReentrantAlgorithm_test.cxx
@@ -40,8 +40,7 @@ public:
 
   virtual StatusCode execute_r (const EventContext& ctx) const override;
 
-  virtual void declareInput(Gaudi::DataHandle* im) override;
-  virtual void declareOutput(Gaudi::DataHandle* im) override;
+  virtual void declare(Gaudi::DataHandle& hnd) override;
 
   SG::ReadHandleKey<MyObj> rkey;
   SG::WriteHandle<MyObj> whandle;
@@ -66,15 +65,11 @@ StatusCode MyAlg::execute_r (const EventContext& ctx) const
 }
 
 
-void MyAlg::declareInput(Gaudi::DataHandle* im)
-{
-  inputs.push_back (im);
-}
-
-
-void MyAlg::declareOutput(Gaudi::DataHandle* im)
-{
-  outputs.push_back (im);
+void MyAlg::declare(Gaudi::DataHandle& hnd) {
+  if (hnd.mode() & Gaudi::DataHandle::Reader) 
+    inputs.push_back( &hnd );
+  if (hnd.mode() & Gaudi::DataHandle::Writer) 
+    outputs.push_back( &hnd );
 }
 
 
diff --git a/Control/AthenaBaseComps/test/propertyHandling_test.cxx b/Control/AthenaBaseComps/test/propertyHandling_test.cxx
index c45eeee2753..b56c835ef5e 100644
--- a/Control/AthenaBaseComps/test/propertyHandling_test.cxx
+++ b/Control/AthenaBaseComps/test/propertyHandling_test.cxx
@@ -41,8 +41,7 @@ public:
 
   virtual StatusCode execute() override;
 
-  virtual void declareInput(Gaudi::DataHandle* im) override;
-  virtual void declareOutput(Gaudi::DataHandle* im) override;
+  virtual void declare(Gaudi::DataHandle& hnd) override;
 
   SG::ReadHandleKey<MyObj> rkey;
   SG::WriteHandleKey<MyObj> wkey;
@@ -74,16 +73,11 @@ StatusCode MyAthAlgorithm::execute()
   return StatusCode::SUCCESS;
 }
 
-
-void MyAthAlgorithm::declareInput(Gaudi::DataHandle* im)
-{
-  inputs.push_back (im);
-}
-
-
-void MyAthAlgorithm::declareOutput(Gaudi::DataHandle* im)
-{
-  outputs.push_back (im);
+void MyAthAlgorithm::declare(Gaudi::DataHandle& hnd) {
+  if (hnd.mode() & Gaudi::DataHandle::Reader) 
+    inputs.push_back( &hnd );
+  if (hnd.mode() & Gaudi::DataHandle::Writer) 
+    outputs.push_back( &hnd );
 }
 
 
@@ -95,8 +89,7 @@ public:
                 const std::string& name,
                 IInterface* parent);
 
-  virtual void declareInput(Gaudi::DataHandle* im) override;
-  virtual void declareOutput(Gaudi::DataHandle* im) override;
+  virtual void declare(Gaudi::DataHandle& hnd) override;
 
   SG::ReadHandleKey<MyObj> rkey;
   SG::WriteHandleKey<MyObj> wkey;
@@ -125,15 +118,11 @@ MyAthAlgTool::MyAthAlgTool  (const std::string& type,
 }
 
 
-void MyAthAlgTool::declareInput(Gaudi::DataHandle* im)
-{
-  inputs.push_back (im);
-}
-
-
-void MyAthAlgTool::declareOutput(Gaudi::DataHandle* im)
-{
-  outputs.push_back (im);
+void MyAthAlgTool::declare(Gaudi::DataHandle& hnd) {
+  if (hnd.mode() & Gaudi::DataHandle::Reader) 
+    inputs.push_back( &hnd );
+  if (hnd.mode() & Gaudi::DataHandle::Writer) 
+    outputs.push_back( &hnd );
 }
 
 
-- 
GitLab