From 2a0ab82dd67e85e3f2154aec09a50067264e8217 Mon Sep 17 00:00:00 2001
From: Scott Snyder <scott.snyder@cern.ch>
Date: Tue, 27 Dec 2016 22:47:02 +0100
Subject: [PATCH] 'Use STL version of unordered_map.' (AthenaKernel-00-60-09)

	* Tagging AthenaKernel-00-60-09.
	* Use STL version of unordered_map.

2016-12-08  Peter van Gemmeren <gemmeren@anl.gov>

	* Tagging AthenaKernel-00-60-08
	* AthenaKernel/IAthenaSelectorTool.h: Make preNext() and postNext()
	const to deal with Gaudi changes.

2016-12-07 Jack Cranshaw <cranshaw@anl.gov>
	* Change IDecisionSvc get methods to return reference rather than
	pointer
	* extend isEventAccepted to be EventContext aware
	* AthenaKernel-00-60-07

2016-12-02 Attila Krasznahorkay <Attila.Krasznahorkay@cern.ch>
	* Removed the genCLIDDB executable from the package, to move it
	  to CLIDComps instead.
	* Updated the package's CMake configuration to be a bit more
...
(Long ChangeLog diff - truncated)
---
 Control/AthenaKernel/AthenaKernel/DsoDb.h     |   4 +-
 .../AthenaKernel/IAthenaSelectorTool.h        |   4 +-
 .../AthenaKernel/IAthenaSerializeSvc.h        |   7 +-
 .../AthenaKernel/AthenaKernel/IDecisionSvc.h  |  10 +-
 .../AthenaKernel/IEvtIdModifierSvc.h          |   2 +-
 .../AthenaKernel/AthenaKernel/IInputRename.h  |  61 +++
 Control/AthenaKernel/AthenaKernel/IRCUSvc.h   |  87 ++++
 Control/AthenaKernel/AthenaKernel/RCUObject.h | 484 ++++++++++++++++++
 .../AthenaKernel/AthenaKernel/RCUObject.icc   | 365 +++++++++++++
 .../AthenaKernel/AthenaKernel/StreamLogger.h  |  73 ---
 .../AthenaKernel/AthenaKernel/errorcheck.h    |   4 +-
 Control/AthenaKernel/CMakeLists.txt           | 120 +++--
 Control/AthenaKernel/cmt/requirements         |   6 +-
 Control/AthenaKernel/share/IRCUSvc_test.ref   |   1 +
 Control/AthenaKernel/share/RCUObject_test.ref |   3 +
 Control/AthenaKernel/src/IClassIDSvc.cxx      |  49 --
 Control/AthenaKernel/src/RCUObject.cxx        |  60 +++
 Control/AthenaKernel/src/StreamLogger.cxx     |  68 ---
 Control/AthenaKernel/test/IRCUSvc_test.cxx    |  73 +++
 Control/AthenaKernel/test/RCUObject_test.cxx  | 265 ++++++++++
 Control/AthenaKernel/test/errorcheck_test.cxx |   6 +-
 Control/AthenaKernel/utils/genCLIDDB.cxx      | 138 -----
 22 files changed, 1479 insertions(+), 411 deletions(-)
 create mode 100644 Control/AthenaKernel/AthenaKernel/IInputRename.h
 create mode 100644 Control/AthenaKernel/AthenaKernel/IRCUSvc.h
 create mode 100644 Control/AthenaKernel/AthenaKernel/RCUObject.h
 create mode 100644 Control/AthenaKernel/AthenaKernel/RCUObject.icc
 delete mode 100644 Control/AthenaKernel/AthenaKernel/StreamLogger.h
 create mode 100644 Control/AthenaKernel/share/IRCUSvc_test.ref
 create mode 100644 Control/AthenaKernel/share/RCUObject_test.ref
 delete mode 100644 Control/AthenaKernel/src/IClassIDSvc.cxx
 create mode 100644 Control/AthenaKernel/src/RCUObject.cxx
 delete mode 100644 Control/AthenaKernel/src/StreamLogger.cxx
 create mode 100644 Control/AthenaKernel/test/IRCUSvc_test.cxx
 create mode 100644 Control/AthenaKernel/test/RCUObject_test.cxx
 delete mode 100644 Control/AthenaKernel/utils/genCLIDDB.cxx

diff --git a/Control/AthenaKernel/AthenaKernel/DsoDb.h b/Control/AthenaKernel/AthenaKernel/DsoDb.h
index 253773f42d0..734e92c319a 100644
--- a/Control/AthenaKernel/AthenaKernel/DsoDb.h
+++ b/Control/AthenaKernel/AthenaKernel/DsoDb.h
@@ -16,7 +16,7 @@
 #include <string>
 #include <vector>
 #include <map>
-#include "CxxUtils/unordered_map.h" // migrate to STL
+#include <unordered_map>
 
 #include "DataModelRoot/RootType.h"
 
@@ -33,7 +33,7 @@ class DsoDb
   /////////////////////////////////////////////////////////////////// 
 public: 
   typedef std::vector<std::string> Libs_t;
-  typedef SG::unordered_map<std::string, Libs_t> DsoMap_t;
+  typedef std::unordered_map<std::string, Libs_t> DsoMap_t;
   //typedef std::map<std::string, Libs_t> DsoMap_t;
 
   // helper functions for pythonizations
diff --git a/Control/AthenaKernel/AthenaKernel/IAthenaSelectorTool.h b/Control/AthenaKernel/AthenaKernel/IAthenaSelectorTool.h
index e6eda6ac25e..02bd377a273 100644
--- a/Control/AthenaKernel/AthenaKernel/IAthenaSelectorTool.h
+++ b/Control/AthenaKernel/AthenaKernel/IAthenaSelectorTool.h
@@ -28,9 +28,9 @@ public:
    /// Called at the end of initialize
    virtual StatusCode postInitialize() = 0;
    /// Called at the beginning of next
-   virtual StatusCode preNext() = 0;
+   virtual StatusCode preNext() const = 0;
    /// Called at the end of next
-   virtual StatusCode postNext() = 0;
+   virtual StatusCode postNext() const = 0;
    /// Called at the beginning of finalize
    virtual StatusCode preFinalize() = 0;
    /// Finalize AlgTool
diff --git a/Control/AthenaKernel/AthenaKernel/IAthenaSerializeSvc.h b/Control/AthenaKernel/AthenaKernel/IAthenaSerializeSvc.h
index e95cebc0075..21d43ab034c 100644
--- a/Control/AthenaKernel/AthenaKernel/IAthenaSerializeSvc.h
+++ b/Control/AthenaKernel/AthenaKernel/IAthenaSerializeSvc.h
@@ -6,6 +6,7 @@
 #define ATHENAKERNEL_IATHENASERIALIZESVC_H
 
 #include "GaudiKernel/IService.h"
+#include "DataModelRoot/RootType.h"
 
 class Guid;
 
@@ -17,9 +18,11 @@ public:
  
    virtual void* serialize(const void* object, const std::string& name, size_t& nbytes) = 0;
    virtual void* serialize(const void* object, const Guid& id, size_t& nbytes) = 0;
+   virtual void* serialize(const void* object, const RootType& cltype, size_t& nbytes) = 0;
 
-   virtual void* deserialize(void* buffer, size_t nbytes, const std::string& name) = 0;
-   virtual void* deserialize(void* buffer, size_t nbytes, const Guid& id) = 0;
+   virtual void* deserialize(void* buffer, size_t& nbytes, const std::string& name) = 0;
+   virtual void* deserialize(void* buffer, size_t& nbytes, const Guid& id) = 0;
+   virtual void* deserialize(void* buffer, size_t& nbytes, const RootType& cltype) = 0;
 };
 
 #endif
diff --git a/Control/AthenaKernel/AthenaKernel/IDecisionSvc.h b/Control/AthenaKernel/AthenaKernel/IDecisionSvc.h
index d1f8bdd0b0f..81a3a782838 100644
--- a/Control/AthenaKernel/AthenaKernel/IDecisionSvc.h
+++ b/Control/AthenaKernel/AthenaKernel/IDecisionSvc.h
@@ -25,6 +25,7 @@
 
 // fwd declares
 class INamedInterface;
+class EventContext;
 
 
 class IDecisionSvc  
@@ -57,19 +58,20 @@ public:
 
   // Get methods of Accept/Require/Veto algorithms for a given stream
   virtual 
-  const std::vector<std::string> * getAcceptAlgs(const std::string& stream) const = 0;
+  const std::vector<std::string> getAcceptAlgs(const std::string& stream) const = 0;
 
   virtual 
-  const std::vector<std::string> * getRequireAlgs(const std::string& stream) const = 0;
+  const std::vector<std::string> getRequireAlgs(const std::string& stream) const = 0;
   
   virtual 
-  const std::vector<std::string> * getVetoAlgs(const std::string& stream) const = 0;
+  const std::vector<std::string> getVetoAlgs(const std::string& stream) const = 0;
 
   // Get list of streams
-  virtual const std::vector<std::string>* getStreams() const = 0;
+  virtual const std::vector<std::string> getStreams() const = 0;
 
   /// Test whether this event should be output, of a given stream
   virtual bool isEventAccepted(const std::string& stream) const = 0;
+  virtual bool isEventAccepted(const std::string& stream, const EventContext&) const = 0;
 
 
   static const InterfaceID& interfaceID();
diff --git a/Control/AthenaKernel/AthenaKernel/IEvtIdModifierSvc.h b/Control/AthenaKernel/AthenaKernel/IEvtIdModifierSvc.h
index 1489ef446d1..397aae4afe4 100644
--- a/Control/AthenaKernel/AthenaKernel/IEvtIdModifierSvc.h
+++ b/Control/AthenaKernel/AthenaKernel/IEvtIdModifierSvc.h
@@ -55,7 +55,7 @@ class IEvtIdModifierSvc
 
   /** @brief return the current evt-nbr (after modification)
    */
-  virtual number_type event_number() const =0;
+  virtual uint64_t event_number() const =0;
 
   /** @brief return the current time-stamp (after modification)
    */
diff --git a/Control/AthenaKernel/AthenaKernel/IInputRename.h b/Control/AthenaKernel/AthenaKernel/IInputRename.h
new file mode 100644
index 00000000000..ec878efd39e
--- /dev/null
+++ b/Control/AthenaKernel/AthenaKernel/IInputRename.h
@@ -0,0 +1,61 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file AthenaKernel/IInputRename.h
+ * @author scott snyder <snyder@bnl.gov>
+ * @date Sep, 2016
+ * @brief Interface to retrieve input rename map.
+ */
+
+
+#ifndef ATHENAKERNEL_IINPUTRENAME_H
+#define ATHENAKERNEL_IINPUTRENAME_H
+
+
+#include "AthenaKernel/sgkey_t.h"
+#include "AthenaKernel/RCUObject.h"
+#include "GaudiKernel/IInterface.h"
+#include <unordered_map>
+
+
+namespace Athena {
+
+
+/**
+ * @brief Interface to retrieve input rename map.
+ *
+ * The address remapping service may be configured to rename objects on input.
+ * When this is done, the keys stored in ElementLink/DataLink also need to
+ * be adjusted.  This interface allows fetching a map that gives the
+ * needed transformation of SG keys.  The returned object is
+ * synchronized via RCU.
+ */
+class IInputRename
+  : virtual public IInterface
+{
+public:
+  /// Type of the input rename map: sgkey_t -> sgkey_t.
+  typedef std::unordered_map<SG::sgkey_t, SG::sgkey_t> InputRenameMap_t;
+  typedef RCUObject<InputRenameMap_t> InputRenameRCU_t;
+
+  DeclareInterfaceID (IInputRename,1,0);
+
+
+  /**
+   * @brief Retrieve a pointer to the input rename map.
+   *
+   * May return null if no renaming is to be done.
+   */
+  virtual const InputRenameRCU_t* inputRenameMap() const = 0;
+};
+
+
+} // namespace Athena
+
+
+#endif // not ATHENAKERNEL_IINPUTRENAME_H
diff --git a/Control/AthenaKernel/AthenaKernel/IRCUSvc.h b/Control/AthenaKernel/AthenaKernel/IRCUSvc.h
new file mode 100644
index 00000000000..96290c30f1c
--- /dev/null
+++ b/Control/AthenaKernel/AthenaKernel/IRCUSvc.h
@@ -0,0 +1,87 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file AthenaKernel/IRCUSvc.h
+ * @author scott snyder <snyder@bnl.gov>
+ * @date Aug, 2016
+ * @brief read-copy-update (RCU) style synchronization for Athena.
+ */
+
+
+#ifndef ATHENAKERNEL_IRCUSVC_H
+#define ATHENAKERNEL_IRCUSVC_H
+
+
+#include "AthenaKernel/RCUObject.h"
+#include "CxxUtils/make_unique.h"
+#include "GaudiKernel/IInterface.h"
+#include <memory>
+
+
+namespace Athena {
+
+
+/**
+ * @brief Interface for RCU service.
+ *
+ * See RCUObject.h for details of the RCU facility.
+ *
+ * The RCU service allows creating new RCU objects and registering
+ * them with the service, and also allows removing them from the service.
+ * The service will declare all registered RCU objects as quiescent
+ * at the end of an event.
+ */
+class IRCUSvc
+  : virtual public IInterface
+{
+public:
+  DeclareInterfaceID (IRCUSvc,1,0);
+
+
+  /**
+   * @brief Make a new RCU object.
+   * @param args... Arguments to pass to the @c T constructor.
+   *
+   * The object will be registered with the service.
+   */
+  template <class T, typename... Args>
+  std::unique_ptr<RCUObject<T> > newrcu (Args&&... args)
+  {
+    auto obj = CxxUtils::make_unique<RCUObject<T> > (*this,
+                                                     std::forward<Args>(args)...);
+    add (obj.get());
+    return obj; 
+  }
+
+
+  /**
+   * @brief Remove an object from the service.
+   * @param obj The object to remove.
+   */
+  virtual StatusCode remove (IRCUObject* obj) = 0;
+
+
+  /**
+   * @brief Return the number of event slots.
+   */
+  virtual size_t getNumSlots() const = 0;
+
+
+private:
+  /**
+   * @brief Remove an object from the service.
+   * @param obj The object to add.
+   */
+  virtual void add (IRCUObject* obj) = 0;
+};
+
+
+} // namespace Athena
+
+
+#endif // not ATHENAKERNEL_IRCUSVC_H
diff --git a/Control/AthenaKernel/AthenaKernel/RCUObject.h b/Control/AthenaKernel/AthenaKernel/RCUObject.h
new file mode 100644
index 00000000000..44d75570d90
--- /dev/null
+++ b/Control/AthenaKernel/AthenaKernel/RCUObject.h
@@ -0,0 +1,484 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file AthenaKernel/RCUObject.h
+ * @author scott snyder <snyder@bnl.gov>
+ * @date Aug, 2016
+ * @brief read-copy-update (RCU) style synchronization for Athena.
+ *
+ * Read-copy-update (RCU) is a style of synchronization that is appropriate
+ * to a read-often, update-seldom case.  More precisely:
+ *
+ *  - Reads are frequent and low overhead is important.
+ *  - Updates are infrequent, and extra overhead doesn't matter much.
+ *  - Exact time ordering between reads and updates is not important.
+ *    That is, if a read happens at about the same time as an update,
+ *    it doesn't matter if the read sees the data before or after
+ *    the update (as long as the reader sees something that is consistent).
+ *
+ * For a more detailed introduction see, for example:
+ *
+ *    <https://lwn.net/Articles/262464>
+ *    <https://lwn.net/Articles/573424>
+ *
+ * There are many different styles of RCU implemenation; the one we implement
+ * here is close to the `quiescent-state-based RCU' (QSBR) variant discussed
+ * in the second article above.  Here, readers take out no locks whatsoever.
+ * It follows then that the updater cannot directly change the object
+ * that is being read.  Instead, it makes an updated copy of the object
+ * and then publishes it by atomically changing a pointer to the object.
+ * The remaining question is then when can the old object be deleted.
+ * It is necessary to delay this until until no thread can be reading
+ * the old version of the object.
+ *
+ * In this implementation, the updater does not wait for this to happen.
+ * Instead, after the update, each event slot (other than the updater)
+ * is marked as being in a `grace' period (via an array of flags
+ * in RCUObject).  A grace period ends for a given event slot when
+ * the object is declared `quiescent'; that is, it is at that time
+ * not referencing the object.  Once the grace periods for all event
+ * slots have finished, then old versions of the object can be deleted.
+ *
+ * It is possible to explicitly declare an object as quiescent, either
+ * by calling the quiescent() method or by using RCUReadQuiesce.
+ * Objects can also be registered with the Athena RCUSvc, which will
+ * declare objects quiescent at the end of an event.
+ *
+ * The current implementation is very simple, and is suitable for a small
+ * number of objects that change infrequently.
+ *
+ *   - If objects are being updated ~ every event and one is relying
+ *     on RCUSvc to mark them as quiescent, then it's possible that we'll
+ *     never be out of the grace period for all event slots simultaneously,
+ *     preventing objects from being cleaned up.
+ *
+ *   - If there are a large number of infrequently-changing objects,
+ *     then RCUSvc may waste time marking as quiescent objects that
+ *     have not changed.
+ *
+ *  If either of these becomes an issue, they can be addressed with a more
+ *  elaborate implementation.
+ *
+ * Usage:
+ *
+ *  The usual usage is to create an RCUObject instance via the RCUSvc.
+ *  RCUObject is templated on the type of the controlled object.
+ *
+ *@code
+ *  ServiceHandle<Athena::RCUSvc> rcusvc ("Athean::RCUSvc", "test");
+ *  std::unique_ptr<Athena::RCUObject<Payload> > =
+ *    rcusvc->newrcu<Payload>();
+ @endcode
+ *
+ * @c newrcu may also take additional arguments that will be passed
+ * to the constructor for @c Payload.  This will register the object
+ * with the service.  One can alternately create a @c RCUObject directly,
+ * passing it the number of event slots.
+ *
+ * To read the controlled object, create a @c RCURead object:
+ *
+ *@code
+ *  const Athena::RCUObject<Payload>& rcuobj = ...;
+ *  {
+ *    Athena::RCURead<Payload> r (rcuobj);
+ *    ret = r->someMethodOnPayload();
+ *  }
+ @endcode
+ *
+ * and to update use @c RCUUpdate:
+ *
+ *@code
+ *  Athena::RCUObject<Payload>& rcuobj = ...;
+ *  {
+ *    Athena::RCUUpdate<Payload> u (rcuobj);
+ *    auto newPayload = std::make_unique<Payload> (*u);
+ *    newPayload->updateSomeStuff();
+ *    u.update (std::move (newPayload));
+ *  }
+ @endcode
+ *
+ * To explicitly declare an object as quiescent, call the @c quiescent method.
+ * This takes an @c EventContext object, or it can be defaulted, in which
+ * case the current global context object will be used.  You can also
+ * use @c RCUReadQuiesce instead of @c RCURead to automatically call
+ * @c quiescent when the read is complete (when the @c RCUReadQuiesce
+ * object is destroyed).
+ */
+
+
+#ifndef ATHENAKERNEL_RCUOBJECT_H
+#define ATHENAKERNEL_RCUOBJECT_H
+
+
+#include "CxxUtils/make_unique.h"
+#include "GaudiKernel/ThreadLocalContext.h"
+#include "GaudiKernel/EventContext.h"
+#include "boost/dynamic_bitset.hpp"
+#include <atomic>
+#include <deque>
+#include <vector>
+#include <memory>
+#include <mutex>
+
+
+namespace Athena {
+
+
+class IRCUSvc;
+template <class T> class RCURead;
+template <class T> class RCUReadQuiesce;
+template <class T> class RCUUpdate;
+
+
+
+/**
+ * @brief Base object class for RCU-style synchronization for Athena.
+ */
+class IRCUObject
+{
+public:
+  /**
+   * @brief Constructor, with RCUSvc.
+   * @param svc Service with which to register.
+   *
+   * The service will call @c quiescent at the end of each event.
+   */
+  IRCUObject (IRCUSvc& svc);
+
+
+  /**
+   * @brief Constructor, with event slot count.
+   * @param nslots Number of active event slots.
+   *
+   * This version does not register with a service.
+   */
+  IRCUObject (size_t nslots);
+
+
+  /**
+   * @brief Destructor.
+   *
+   * Remove this object from the service if it has been registered.
+   */
+  virtual ~IRCUObject();
+
+
+  /**
+   * @brief Declare the current event slot of this object to be quiescent.
+   *
+   * This will take out a lock and possibly trigger object cleanup.
+   */
+  void quiescent();
+
+
+  /**
+   * @brief Declare the event slot @c ctx of this object to be quiescent.
+   * @param ctx The event context.
+   *
+   * This will take out a lock and possibly trigger object cleanup.
+   */
+  void quiescent (const EventContext& ctx);
+
+
+protected:
+  typedef std::mutex mutex_t;
+  typedef std::lock_guard<mutex_t> lock_t;
+
+
+  /**
+   * @brief Declare that the grace period for a slot is ending.
+   * @param Lock object (external locking).
+   * @param ctx Event context for the slot.
+   * @returns true if any slot is still in a grace period.
+   *          false if no slots are in a grace period.
+   *
+   * The caller must be holding the mutex for this object.
+   */
+  bool endGrace (lock_t& /*lock*/, const EventContext& ctx);
+
+
+  /**
+   * @brief Declare that all slots are in a grace period.
+   * @param Lock object (external locking).
+   * @param ctx Event context for the slot.
+   *
+   * The caller must be holding the mutex for this object.
+   */
+  void setGrace (lock_t& /*lock*/);
+
+
+  /**
+   * @brief Return the mutex for this object.
+   */
+  mutex_t& mutex();
+
+
+  /**
+   * @brief Delete all old objects.
+   * @param Lock object (external locking).
+   *
+   * The caller must be holding the mutex for this object.
+   */
+  virtual void clearOld (lock_t& /*lock*/) = 0;
+
+
+private:
+  /// The mutex for this object.
+  std::mutex m_mutex;
+
+  /// The service with which we're registered, or null.
+  IRCUSvc* m_svc;
+
+  /// Bit[i] set means that slot i is in a grace period.
+  boost::dynamic_bitset<> m_grace;
+};
+
+
+/**
+ * @brief Wrapper object controlled by RCU synchonization.
+ *
+ * See the comments at the top of the file for complete comments.
+ */
+template <class T>
+class RCUObject
+  : public IRCUObject
+{
+public:
+  typedef RCURead<T> Read_t;
+  typedef RCUReadQuiesce<T> ReadQuiesce_t;
+  typedef RCUUpdate<T> Update_t;
+
+
+  /**
+   * @brief Constructor, with RCUSvc.
+   * @param svc Service with which to register.
+   * @param args... Additional arguments to pass to the @c T constructor.
+   *
+   * The service will call @c quiescent at the end of each event.
+   */
+  template <typename... Args>
+  RCUObject (IRCUSvc& svc, Args&&... args);
+
+
+  /**
+   * @brief Constructor, with number of slots.
+   * @param nslots Number of event slots.
+   * @param args... Additional arguments to pass to the @c T constructor.
+   */
+  template <typename... Args>
+  RCUObject (size_t nslots, Args&&... args);
+
+
+  /**
+   * @brief Return a reader for this @c RCUObject.
+   */
+  Read_t reader() const;
+
+
+  /**
+   * @brief Return a reader for this @c RCUObject.
+   *        When destroyed, this reader will declare
+   *        the @c RCUObject as quiescent
+   *
+   * This version will read the global event context.
+   */
+  ReadQuiesce_t readerQuiesce();
+
+
+  /**
+   * @brief Return a reader for this @c RCUObject.
+   *        When destroyed, this reader will declare
+   *        the @c RCUObject as quiescent
+   * @param ctx The event context.
+   */
+  ReadQuiesce_t readerQuiesce (const EventContext& ctx);
+
+
+  /**
+   * @brief Return an updater for this @c RCUObject.
+   *
+   * This version will read the global event context.
+   */
+  Update_t updater();
+
+
+  /**
+   * @brief Return an updater for this @c RCUObject.
+   * @param ctx The event context.
+   */
+  Update_t updater (const EventContext& ctx);
+
+
+private:
+  /**
+   * @brief Delete all old objects.
+   * @param Lock object (external locking).
+   *
+   * The caller must be holding the mutex for this object.
+   */
+  virtual void clearOld (lock_t& /*lock*/) override;
+
+
+private:
+  template <class U> friend class RCUReadQuiesce;
+  template <class U> friend class RCURead;
+  template <class U> friend class RCUUpdate;
+
+  /// Pointer to the current object.
+  std::atomic<const T*> m_obj;
+
+  /// List of all allocated objects.
+  /// The current object is the one at the front;
+  /// the others are pending cleanup.
+  std::deque<std::unique_ptr<T> > m_objs;
+};
+
+
+/**
+ * @brief Helper to read data from a @c RCUObject.
+ * 
+ * See the header comments for details.
+ */
+template <class T>
+class RCURead
+{
+public:
+  /**
+   * @brief Constructor.
+   * @param rcuobj The @c RCUObject we're reading.
+   */
+  RCURead (const RCUObject<T>& rcuobj);
+
+
+  /**
+   * @brief Access data.
+   */
+  const T& operator*() const;
+
+
+  /**
+   * @brief Access data.
+   */
+  const T* operator->() const;
+
+  
+private:
+  /// The data object we're reading.
+  const T& m_obj;
+};
+
+
+/**
+ * @brief Helper to read data from a @c RCUObject.
+ *        When this object is deleted, the @c RCUObject is declared
+ *        quiescent for this event slot.
+ * 
+ * See the header comments for details.
+ */
+template <class T>
+class RCUReadQuiesce
+  : public RCURead<T>
+{
+public:
+  /**
+   * @brief Constructor.
+   * @param rcuobj The @c RCUObject we're reading.
+   *
+   * This version will read the global event context.
+   */
+  RCUReadQuiesce (RCUObject<T>& rcuobj);
+
+
+  /**
+   * @brief Constructor.
+   * @param rcuobj The @c RCUObject we're reading.
+   * @param ctx The event context.
+   */
+  RCUReadQuiesce (RCUObject<T>& rcuobj, const EventContext& ctx);
+
+
+  /**
+   * @brief Destructor.
+   *
+   * Mark this event slot quiescent.
+   */
+  ~RCUReadQuiesce();
+
+
+private:
+  /// The RCUObject we're referencing.
+  RCUObject<T>& m_rcuobj;
+
+  /// The current event context.
+  const EventContext& m_ctx;
+};
+
+
+/**
+ * @brief Helper to update data in a @c RCUObject.
+ * 
+ * See the header comments for details.
+ */
+template <class T>
+class RCUUpdate
+{
+public:
+  /**
+   * @brief Constructor.
+   * @param rcuobj The @c RCUObject we're reading.
+   *
+   * This version will read the global event context.
+   */
+  RCUUpdate (RCUObject<T>& rcuobj);
+
+  
+  /**
+   * @brief Constructor.
+   * @param rcuobj The @c RCUObject we're reading.
+   * @param ctx The event context.
+   */
+  RCUUpdate (RCUObject<T>& rcuobj, const EventContext& ctx);
+
+  
+  /**
+   * @brief Access data.
+   */
+  const T& operator*() const;
+
+
+  /**
+   * @brief Access data.
+   */
+  const T* operator->() const;
+
+
+  /**
+   * @brief Publish a new version of the data object.
+   * @param ptr The new data object.
+   */
+  void update (std::unique_ptr<T> ptr);
+
+private:
+  /// The object we're referencing.
+  RCUObject<T>& m_rcuobj;
+
+  /// The event context.
+  const EventContext& m_ctx;
+
+  /// Lock for synchonization.
+  std::lock_guard<std::mutex> m_g;
+};
+
+
+} // namespace Athena
+
+
+#include "AthenaKernel/RCUObject.icc"
+
+
+#endif // not ATHENAKERNEL_RCUOBJECT_H
diff --git a/Control/AthenaKernel/AthenaKernel/RCUObject.icc b/Control/AthenaKernel/AthenaKernel/RCUObject.icc
new file mode 100644
index 00000000000..711487e5632
--- /dev/null
+++ b/Control/AthenaKernel/AthenaKernel/RCUObject.icc
@@ -0,0 +1,365 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file AthenaKernel/RCUObject.icc
+ * @author scott snyder <snyder@bnl.gov>
+ * @date Aug, 2016
+ * @brief read-copy-update (RCU) style synchronization for Athena.
+ */
+
+
+namespace Athena {
+
+
+/**
+ * @brief Declare the current event slot of this object to be quiescent.
+ *
+ * This will take out a lock and possibly trigger object cleanup.
+ */
+inline
+void IRCUObject::quiescent()
+{
+  quiescent (Gaudi::Hive::currentContext());
+}
+
+
+/**
+ * @brief Declare the event slot @c ctx of this object to be quiescent.
+ * @param ctx The event context.
+ *
+ * This will take out a lock and possibly trigger object cleanup.
+ */
+inline
+void IRCUObject::quiescent (const EventContext& ctx)
+{
+  std::lock_guard<std::mutex> g (m_mutex);
+  if (endGrace(g, ctx)) return;
+  clearOld(g);
+}
+
+
+/**
+ * @brief Declare that the grace period for a slot is ending.
+ * @param Lock object (external locking).
+ * @param ctx Event context for the slot.
+ * @returns true if any slot is still in a grace period.
+ *          false if no slots are in a grace period.
+ *
+ * The caller must be holding the mutex for this object.
+ */
+inline
+bool IRCUObject::endGrace (lock_t& /*lock*/, const EventContext& ctx)
+{
+  EventContext::ContextID_t slot = ctx.slot();
+  if (slot == EventContext::INVALID_CONTEXT_ID) return false;
+  if (slot >= m_grace.size()) std::abort();
+  m_grace[slot] = false;
+  return m_grace.any();
+}
+
+
+/**
+ * @brief Declare that all slots are in a grace period.
+ * @param Lock object (external locking).
+ * @param ctx Event context for the slot.
+ *
+ * The caller must be holding the mutex for this object.
+ */
+inline
+void IRCUObject::setGrace (lock_t& /*lock*/)
+{
+  m_grace.set();
+}
+
+
+/**
+ * @brief Return the mutex for this object.
+ */
+inline
+typename IRCUObject::mutex_t& IRCUObject::mutex()
+{
+  return m_mutex;
+}
+
+
+//*************************************************************************
+
+
+/**
+ * @brief Constructor, with RCUSvc.
+ * @param svc Service with which to register.
+ * @param args... Additional arguments to pass to the @c T constructor.
+ *
+ * The service will call @c quiescent at the end of each event.
+ */
+template <class T>
+template <typename... Args>
+inline
+RCUObject<T>::RCUObject (IRCUSvc& svc, Args&&... args)
+  : IRCUObject (svc)
+{
+  m_objs.push_back (CxxUtils::make_unique<T>(std::forward<Args>(args)...));
+  m_obj = m_objs.front().get();
+}
+
+
+/**
+ * @brief Constructor, with number of slots.
+ * @param nslots Number of event slots.
+ * @param args... Additional arguments to pass to the @c T constructor.
+ */
+template <class T>
+template <typename... Args>
+inline
+RCUObject<T>::RCUObject (size_t nslots, Args&&... args)
+  : IRCUObject (nslots)
+{
+  m_objs.push_back (CxxUtils::make_unique<T>(std::forward<Args>(args)...));
+  m_obj = m_objs.front().get();
+}
+
+
+/**
+ * @brief Return a reader for this @c RCUObject.
+ */
+template <class T>
+inline
+typename RCUObject<T>::Read_t RCUObject<T>::reader() const
+{
+  return Read_t (*this);
+}
+
+
+/**
+ * @brief Return a reader for this @c RCUObject.
+ *        When destroyed, this reader will declare
+ *        the @c RCUObject as quiescent
+ *
+ * This version will read the global event context.
+ */
+template <class T>
+inline
+typename RCUObject<T>::ReadQuiesce_t RCUObject<T>::readerQuiesce()
+{
+  return ReadQuiesce_t (*this);
+}
+
+
+/**
+ * @brief Return a reader for this @c RCUObject.
+ *        When destroyed, this reader will declare
+ *        the @c RCUObject as quiescent
+ * @param ctx The event context.
+ */
+template <class T>
+inline
+typename RCUObject<T>::ReadQuiesce_t
+RCUObject<T>::readerQuiesce (const EventContext& ctx)
+{
+  return ReadQuiesce_t (*this, ctx);
+}
+
+
+/**
+ * @brief Return an updater for this @c RCUObject.
+ *
+ * This version will read the global event context.
+ */
+template <class T>
+inline
+typename RCUObject<T>::Update_t RCUObject<T>::updater()
+{
+  return Update_t (*this);
+}
+
+
+/**
+ * @brief Return an updater for this @c RCUObject.
+ *
+ * This version will read the global event context.
+ */
+template <class T>
+inline
+typename RCUObject<T>::Update_t
+RCUObject<T>::updater (const EventContext& ctx)
+{
+  return Update_t (*this, ctx);
+}
+
+
+/**
+ * @brief Delete all old objects.
+ * @param Lock object (external locking).
+ *
+ * The caller must be holding the mutex for this object.
+ */
+template <class T>
+inline
+void RCUObject<T>::clearOld (lock_t& /*lock*/)
+{
+  while (m_objs.size() > 1)
+    m_objs.pop_back();
+}
+
+
+//*************************************************************************
+
+
+/**
+ * @brief Constructor.
+ * @param rcuobj The @c RCUObject we're reading.
+ */
+template <class T>
+inline
+RCURead<T>::RCURead (const RCUObject<T>& rcuobj)
+  : m_obj (*rcuobj.m_obj)
+{
+}
+
+
+/**
+ * @brief Access data.
+ */
+template <class T>
+inline
+const T& RCURead<T>::operator*() const
+{
+  return m_obj;
+}
+
+
+/**
+ * @brief Access data.
+ */
+template <class T>
+inline
+const T* RCURead<T>::operator->() const
+{
+  return &m_obj;
+}
+
+
+//*************************************************************************
+
+
+/**
+ * @brief Constructor.
+ * @param rcuobj The @c RCUObject we're reading.
+ *
+ * This version will read the global event context.
+ */
+template <class T>
+inline
+RCUReadQuiesce<T>::RCUReadQuiesce (RCUObject<T>& rcuobj)
+  : RCURead<T> (rcuobj),
+  m_rcuobj (rcuobj),
+  m_ctx (Gaudi::Hive::currentContext())
+{
+}
+
+
+/**
+ * @brief Constructor.
+ * @param rcuobj The @c RCUObject we're reading.
+ * @param ctx The event context.
+ */
+template <class T>
+inline
+RCUReadQuiesce<T>::RCUReadQuiesce (RCUObject<T>& rcuobj,
+                                   const EventContext& ctx)
+  : RCURead<T> (rcuobj),
+  m_rcuobj (rcuobj),
+  m_ctx (ctx)
+{
+}
+
+
+/**
+ * @brief Destructor.
+ *
+ * Mark this event slot quiescent.
+ */
+template <class T>
+inline
+RCUReadQuiesce<T>::~RCUReadQuiesce()
+{
+  m_rcuobj.quiescent (m_ctx);
+}
+
+
+//*************************************************************************
+
+
+/**
+ * @brief Constructor.
+ * @param rcuobj The @c RCUObject we're reading.
+ *
+ * This version will read the global event context.
+ */
+template <class T>
+inline
+RCUUpdate<T>::RCUUpdate (RCUObject<T>& rcuobj)
+  : m_rcuobj (rcuobj),
+    m_ctx (Gaudi::Hive::currentContext()),
+    m_g (rcuobj.mutex())
+{
+}
+
+
+/**
+ * @brief Constructor.
+ * @param rcuobj The @c RCUObject we're reading.
+ * @param ctx The event context.
+ */
+template <class T>
+inline
+RCUUpdate<T>::RCUUpdate (RCUObject<T>& rcuobj, const EventContext& ctx)
+  : m_rcuobj (rcuobj),
+    m_ctx (ctx),
+    m_g (rcuobj.mutex())
+{
+}
+
+
+/**
+ * @brief Access data.
+ */
+template <class T>
+inline
+const T& RCUUpdate<T>::operator*() const
+{
+  return *m_rcuobj.m_obj;
+}
+
+
+/**
+ * @brief Access data.
+ */
+template <class T>
+inline
+const T* RCUUpdate<T>::operator->() const
+{
+  return m_rcuobj.m_obj;
+}
+
+
+/**
+ * @brief Publish a new version of the data object.
+ * @param ptr The new data object.
+ */
+template <class T>
+void RCUUpdate<T>::update (std::unique_ptr<T> ptr)
+{
+  m_rcuobj.m_objs.push_front (std::move (ptr));
+  m_rcuobj.m_obj = m_rcuobj.m_objs.front().get();
+  m_rcuobj.setGrace(m_g);
+
+  // Go ahead and end the grace period for the current slot.
+  m_rcuobj.endGrace(m_g, m_ctx);
+}
+
+
+} // namespace Athena
diff --git a/Control/AthenaKernel/AthenaKernel/StreamLogger.h b/Control/AthenaKernel/AthenaKernel/StreamLogger.h
deleted file mode 100644
index c9bf0d5fed0..00000000000
--- a/Control/AthenaKernel/AthenaKernel/StreamLogger.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-#ifndef ATHENAKERNEL_STREAMLOGGER_H
-#define ATHENAKERNEL_STREAMLOGGER_H 1
-
-/** 
- * @file StreamLogger.h
- * @brief provide entry point for binding output streams.
- *
- * @author Charles Leggett
- * $Id: StreamLogger.h,v 1.2 2007-06-14 01:57:23 calaf Exp $
- */
-
-#include "GaudiKernel/MsgStream.h"
-
-#include <ostream>
-#include <string>
-
-class IMessageSvc;
-
-/** 
- * @class StreamLogger
- * @brief provide entry point for binding output streams.
- * @details bind with
- * @code
- *  boost::function<void (const std::string&)> streamLog;
- * @endcode
- * for MsgSvc:
- * @code
- *  StreamLogger *logger = new StreamLogger(msgSvc(), MSG::LEVEL, MsgName);
- *  boost::bind(&StreamLogger::WriteToMsgSvc, logger, _1);
- * @endcode
- * for stderr, stdout, etc
- * @code
- *  StreamLogger *logger = new StreamLogger(std::cerr);
- *  streamLog = boost::bind(&StreamLogger::WriteToStream, logger, _1)
- * @endcode
- * for file
- * @code
- *  StreamLogger *logger = new StreamLogger(fileName);
- *  streamLog = boost::bind(&StreamLogger::WriteToStream, logger, _1);
- * @endcode
- * to write out:
- * @code
- *  streamLog("output");
- * @endcode
- */
-class StreamLogger {
-public:
-  StreamLogger(const std::string& file);
-  StreamLogger(std::ostream &ost);
-  StreamLogger(IMessageSvc*, MSG::Level, 
-	       const std::string& msgName="StreamLogger");
-  ~StreamLogger();
-
-  std::string name() const { return m_name; }
-  
-  void WriteToStream(const std::string& str) { *p_ost << str << std::endl; }
-  void WriteToMsgSvc(const std::string& str) { *p_msgStr << m_level << str 
-							 << endmsg; }
-  
-private:
-  bool m_isMine;
-  std::ostream *p_ost;
-  MsgStream *p_msgStr;
-  MSG::Level m_level;
-  std::string m_name;
-};
-
-
-#endif
diff --git a/Control/AthenaKernel/AthenaKernel/errorcheck.h b/Control/AthenaKernel/AthenaKernel/errorcheck.h
index 00e5cbb0bbc..01d4cb71fd3 100644
--- a/Control/AthenaKernel/AthenaKernel/errorcheck.h
+++ b/Control/AthenaKernel/AthenaKernel/errorcheck.h
@@ -17,7 +17,7 @@
  *@code
  *  StatusCode sc = something();
  *  if (! sc.isSuccess() ) {
- *    log << "Some error message" << endreq;
+ *    log << "Some error message" << endmsg;
  *    return sc;
  *  }
  @endcode
@@ -62,7 +62,7 @@
  * error reporting provided here with the macro
  * @c REPORT_ERROR, which takes a @c StatusCode as an argument.
  * Additional text can be added with the output streaming operator,
- * as for @c MsgStream.  (No need to use @c endreq.)
+ * as for @c MsgStream.  (No need to use @c endmsg.)
  *
  *@code
  *  StatusCode sc = something();
diff --git a/Control/AthenaKernel/CMakeLists.txt b/Control/AthenaKernel/CMakeLists.txt
index a62f120d48d..444b4172257 100644
--- a/Control/AthenaKernel/CMakeLists.txt
+++ b/Control/AthenaKernel/CMakeLists.txt
@@ -1,3 +1,4 @@
+# $Id: CMakeLists.txt 787829 2016-12-02 10:10:58Z krasznaa $
 ################################################################################
 # Package: AthenaKernel
 ################################################################################
@@ -6,93 +7,86 @@
 atlas_subdir( AthenaKernel )
 
 # Declare the package's dependencies:
-atlas_depends_on_subdirs( PUBLIC
-                          Control/CxxUtils
-                          Control/DataModelRoot
-                          GaudiKernel
-                          Tools/Scripts
-                          PRIVATE
-                          AtlasTest/TestTools )
+atlas_depends_on_subdirs(
+   PUBLIC
+   Control/CxxUtils
+   Control/DataModelRoot
+   GaudiKernel
+   PRIVATE
+   AtlasTest/TestTools )
 
 # External dependencies:
-find_package( Boost COMPONENTS program_options regex filesystem system thread )
-find_package( ROOT COMPONENTS Core Tree MathCore Hist RIO pthread )
+find_package( Boost COMPONENTS program_options regex filesystem thread )
+find_package( ROOT COMPONENTS Core )
 find_package( UUID )
 
-# Component(s) in the package:
+# Only link agains the RT library on Linux:
+set( rt_library )
+if( UNIX AND NOT APPLE )
+   set( rt_library rt )
+endif()
+
+# Libraries in the package:
 atlas_add_library( AthenaKernel
-                   src/*.cxx
-                   PUBLIC_HEADERS AthenaKernel
-                   INCLUDE_DIRS ${Boost_INCLUDE_DIRS} ${UUID_INCLUDE_DIRS}
-                   PRIVATE_INCLUDE_DIRS ${ROOT_INCLUDE_DIRS}
-                   LINK_LIBRARIES ${Boost_LIBRARIES} ${UUID_LIBRARIES} CxxUtils DataModelRoot GaudiKernel rt
-                   PRIVATE_LINK_LIBRARIES ${ROOT_LIBRARIES} TestTools )
+   AthenaKernel/*.h AthenaKernel/*.icc src/*.cxx
+   PUBLIC_HEADERS AthenaKernel
+   INCLUDE_DIRS ${Boost_INCLUDE_DIRS} ${UUID_INCLUDE_DIRS}
+   PRIVATE_INCLUDE_DIRS ${ROOT_INCLUDE_DIRS}
+   LINK_LIBRARIES ${Boost_LIBRARIES} ${UUID_LIBRARIES} CxxUtils DataModelRoot
+   GaudiKernel ${rt_library}
+   PRIVATE_LINK_LIBRARIES ${ROOT_LIBRARIES} )
 
 atlas_add_dictionary( AthenaKernelDict
-                      AthenaKernel/AthenaKernelDict.h
-                      AthenaKernel/selection.xml
-                      INCLUDE_DIRS ${Boost_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS} ${UUID_INCLUDE_DIRS}
-                      LINK_LIBRARIES ${Boost_LIBRARIES} ${ROOT_LIBRARIES} ${UUID_LIBRARIES} rt CxxUtils DataModelRoot GaudiKernel TestTools AthenaKernel )
+   AthenaKernel/AthenaKernelDict.h
+   AthenaKernel/selection.xml
+   LINK_LIBRARIES GaudiKernel AthenaKernel )
 
+# Test(s) in the package:
 atlas_add_test( getMessageSvc_test
-                SOURCES
-                test/getMessageSvc_test.cxx
-                INCLUDE_DIRS ${Boost_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS} ${UUID_INCLUDE_DIRS}
-                LINK_LIBRARIES ${Boost_LIBRARIES} ${ROOT_LIBRARIES} ${UUID_LIBRARIES} CxxUtils DataModelRoot GaudiKernel TestTools AthenaKernel
-                EXTRA_PATTERNS "^=========+|^ApplicationMgr +SUCCESS|^HistogramPersis.*INFO.*CnvServices|^StatusCodeSvc +INFO initialize|^ *Welcome to ApplicationMgr|^ *running on|^Wall clock time" )
+   SOURCES test/getMessageSvc_test.cxx
+   LINK_LIBRARIES GaudiKernel TestTools AthenaKernel
+   EXTRA_PATTERNS "^=========+|^ApplicationMgr +SUCCESS|^HistogramPersis.*INFO.*CnvServices|^StatusCodeSvc +INFO initialize|^ *Welcome to ApplicationMgr|^ *running on|^Wall clock time" )
 
 atlas_add_test( MsgStreamMember_test
-                SOURCES
-                test/MsgStreamMember_test.cxx
-                INCLUDE_DIRS ${Boost_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS} ${UUID_INCLUDE_DIRS}
-                LINK_LIBRARIES ${Boost_LIBRARIES} ${ROOT_LIBRARIES} ${UUID_LIBRARIES} CxxUtils DataModelRoot GaudiKernel TestTools AthenaKernel
-                EXTRA_PATTERNS "^=========+|^ApplicationMgr +SUCCESS|^HistogramPersis.*INFO.*CnvServices|^StatusCodeSvc +INFO initialize|^ *Welcome to ApplicationMgr|^ *running on|^Wall clock time |ref count" )
+   SOURCES test/MsgStreamMember_test.cxx
+   LINK_LIBRARIES TestTools AthenaKernel
+   EXTRA_PATTERNS "^=========+|^ApplicationMgr +SUCCESS|^HistogramPersis.*INFO.*CnvServices|^StatusCodeSvc +INFO initialize|^ *Welcome to ApplicationMgr|^ *running on|^Wall clock time |ref count" )
 
 atlas_add_test( AthenaPackageInfo_test
-                SOURCES
-                test/AthenaPackageInfo_test.cxx
-                INCLUDE_DIRS ${Boost_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS} ${UUID_INCLUDE_DIRS}
-                LINK_LIBRARIES ${Boost_LIBRARIES} ${ROOT_LIBRARIES} ${UUID_LIBRARIES} CxxUtils DataModelRoot GaudiKernel TestTools AthenaKernel )
+   SOURCES test/AthenaPackageInfo_test.cxx
+   LINK_LIBRARIES AthenaKernel )
 
 atlas_add_test( DirSearchPath_test
-                SOURCES
-                test/DirSearchPath_test.cxx
-                INCLUDE_DIRS ${Boost_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS} ${UUID_INCLUDE_DIRS}
-                LINK_LIBRARIES ${Boost_LIBRARIES} ${ROOT_LIBRARIES} ${UUID_LIBRARIES} CxxUtils DataModelRoot GaudiKernel TestTools AthenaKernel )
+   SOURCES test/DirSearchPath_test.cxx
+   INCLUDE_DIRS ${Boost_INCLUDE_DIRS}
+   LINK_LIBRARIES ${Boost_LIBRARIES} GaudiKernel )
 
 atlas_add_test( Chrono_test
-                SOURCES
-                test/Chrono_test.cxx
-                INCLUDE_DIRS ${Boost_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS} ${UUID_INCLUDE_DIRS}
-                LINK_LIBRARIES ${Boost_LIBRARIES} ${ROOT_LIBRARIES} ${UUID_LIBRARIES} CxxUtils DataModelRoot GaudiKernel TestTools AthenaKernel )
+   SOURCES test/Chrono_test.cxx
+   LINK_LIBRARIES GaudiKernel AthenaKernel )
 
 atlas_add_test( errorcheck_test
-                SOURCES
-                test/errorcheck_test.cxx
-                INCLUDE_DIRS ${Boost_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS} ${UUID_INCLUDE_DIRS}
-                LINK_LIBRARIES ${Boost_LIBRARIES} ${ROOT_LIBRARIES} ${UUID_LIBRARIES} CxxUtils DataModelRoot GaudiKernel TestTools AthenaKernel
-                EXTRA_PATTERNS "^=========+|^ApplicationMgr +SUCCESS|^HistogramPersis.*INFO.*CnvServices|^StatusCodeSvc +INFO initialize|^ *Welcome to ApplicationMgr|^ *running on|^Wall clock time" )
+   SOURCES test/errorcheck_test.cxx
+   LINK_LIBRARIES GaudiKernel TestTools AthenaKernel
+   EXTRA_PATTERNS "^=========+|^ApplicationMgr +SUCCESS|^HistogramPersis.*INFO.*CnvServices|^StatusCodeSvc +INFO initialize|^ *Welcome to ApplicationMgr|^ *running on|^Wall clock time" )
 
 atlas_add_test( type_tools_test
-                SOURCES
-                test/type_tools_test.cxx
-                INCLUDE_DIRS ${Boost_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS} ${UUID_INCLUDE_DIRS}
-                LINK_LIBRARIES ${Boost_LIBRARIES} ${ROOT_LIBRARIES} ${UUID_LIBRARIES} CxxUtils DataModelRoot GaudiKernel TestTools AthenaKernel )
+   SOURCES test/type_tools_test.cxx
+   LINK_LIBRARIES AthenaKernel )
 
 atlas_add_test( Units_test
-                SOURCES
-                test/Units_test.cxx
-                INCLUDE_DIRS ${Boost_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS} ${UUID_INCLUDE_DIRS}
-                LINK_LIBRARIES ${Boost_LIBRARIES} ${ROOT_LIBRARIES} ${UUID_LIBRARIES} CxxUtils DataModelRoot GaudiKernel TestTools AthenaKernel )
+   SOURCES test/Units_test.cxx
+   LINK_LIBRARIES GaudiKernel TestTools AthenaKernel )
 
 atlas_add_test( DataObjectSharedPtr_test
-                SOURCES
-                test/DataObjectSharedPtr_test.cxx
-                INCLUDE_DIRS ${Boost_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS} ${UUID_INCLUDE_DIRS}
-                LINK_LIBRARIES ${Boost_LIBRARIES} ${ROOT_LIBRARIES} ${UUID_LIBRARIES} CxxUtils DataModelRoot GaudiKernel TestTools AthenaKernel )
+   SOURCES test/DataObjectSharedPtr_test.cxx
+   LINK_LIBRARIES AthenaKernel )
 
-atlas_add_executable( genCLIDDB
-                      utils/genCLIDDB.cxx
-                      INCLUDE_DIRS ${Boost_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS} ${UUID_INCLUDE_DIRS}
-                      LINK_LIBRARIES ${Boost_LIBRARIES} ${ROOT_LIBRARIES} ${UUID_LIBRARIES} CxxUtils DataModelRoot GaudiKernel TestTools AthenaKernel )
+atlas_add_test( IRCUSvc_test
+   SOURCES test/IRCUSvc_test.cxx
+   LINK_LIBRARIES AthenaKernel )
 
+atlas_add_test( RCUObject_test
+   SOURCES test/RCUObject_test.cxx
+   INCLUDE_DIRS ${Boost_INCLUDE_DIRS}
+   LINK_LIBRARIES ${Boost_LIBRARIES} AthenaKernel )
diff --git a/Control/AthenaKernel/cmt/requirements b/Control/AthenaKernel/cmt/requirements
index d0edbb3f2d4..b741604af75 100644
--- a/Control/AthenaKernel/cmt/requirements
+++ b/Control/AthenaKernel/cmt/requirements
@@ -45,14 +45,12 @@ apply_pattern UnitTest_run unit_test=errorcheck extrapatterns="'$(extrapatterns)
 apply_pattern UnitTest_run unit_test=type_tools
 apply_pattern UnitTest_run unit_test=Units
 apply_pattern UnitTest_run unit_test=DataObjectSharedPtr
+apply_pattern UnitTest_run unit_test=IRCUSvc
+apply_pattern UnitTest_run unit_test=RCUObject
 
 macro_append DOXYGEN_INPUT " ../doc ../test ../AthenaKernel/tools " 
 macro_append DOXYGEN_FILE_PATTERNS    " *.icc"
 
-application genCLIDDB ../utils/genCLIDDB.cxx 
-macro_append genCLIDDBlinkopts " $(Boost_linkopts_program_options) "
-macro_append genCLIDDB_dependencies " AthenaKernel"
-
 #
 # dictionary creation for UserDataAssociation
 #
diff --git a/Control/AthenaKernel/share/IRCUSvc_test.ref b/Control/AthenaKernel/share/IRCUSvc_test.ref
new file mode 100644
index 00000000000..a5bce3fd256
--- /dev/null
+++ b/Control/AthenaKernel/share/IRCUSvc_test.ref
@@ -0,0 +1 @@
+test1
diff --git a/Control/AthenaKernel/share/RCUObject_test.ref b/Control/AthenaKernel/share/RCUObject_test.ref
new file mode 100644
index 00000000000..76983460f7f
--- /dev/null
+++ b/Control/AthenaKernel/share/RCUObject_test.ref
@@ -0,0 +1,3 @@
+test1
+test2
+test3
diff --git a/Control/AthenaKernel/src/IClassIDSvc.cxx b/Control/AthenaKernel/src/IClassIDSvc.cxx
deleted file mode 100644
index 95c79b4cc99..00000000000
--- a/Control/AthenaKernel/src/IClassIDSvc.cxx
+++ /dev/null
@@ -1,49 +0,0 @@
-///////////////////////// -*- C++ -*- /////////////////////////////
-
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-// IClassIDSvc.cxx 
-// Implementation file for class IClassIDSvc
-// Author: S.Binet<binet@cern.ch>
-/////////////////////////////////////////////////////////////////// 
-
-// AthenaKernel includes
-#include "AthenaKernel/IClassIDSvc.h"
-
-
-
-/////////////////////////////////////////////////////////////////// 
-// Public methods: 
-/////////////////////////////////////////////////////////////////// 
-
-// Constructors
-////////////////
-
-// Destructor
-///////////////
-IClassIDSvc::~IClassIDSvc()
-{}
-
-/////////////////////////////////////////////////////////////////// 
-// Const methods: 
-///////////////////////////////////////////////////////////////////
-
-/////////////////////////////////////////////////////////////////// 
-// Non-const methods: 
-/////////////////////////////////////////////////////////////////// 
-
-/////////////////////////////////////////////////////////////////// 
-// Protected methods: 
-/////////////////////////////////////////////////////////////////// 
-
-/////////////////////////////////////////////////////////////////// 
-// Const methods: 
-///////////////////////////////////////////////////////////////////
-
-/////////////////////////////////////////////////////////////////// 
-// Non-const methods: 
-/////////////////////////////////////////////////////////////////// 
-
-
diff --git a/Control/AthenaKernel/src/RCUObject.cxx b/Control/AthenaKernel/src/RCUObject.cxx
new file mode 100644
index 00000000000..b46fd9cd07e
--- /dev/null
+++ b/Control/AthenaKernel/src/RCUObject.cxx
@@ -0,0 +1,60 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file AthenaKernel/src/RCUObject.cxx
+ * @author scott snyder <snyder@bnl.gov>
+ * @date Aug, 2016
+ * @brief read-copy-update (RCU) style synchronization for Athena.
+ */
+
+
+#include "AthenaKernel/RCUObject.h"
+#include "AthenaKernel/IRCUSvc.h"
+#include <cstdlib>
+
+
+namespace Athena {
+
+
+/**
+ * @brief Constructor, with RCUSvc.
+ * @param svc Service with which to register.
+ *
+ * The service will call @c quiescent at the end of each event.
+ */
+IRCUObject::IRCUObject (IRCUSvc& svc)
+  : m_svc (&svc),
+    m_grace (svc.getNumSlots())
+{
+}
+
+
+/**
+ * @brief Constructor, with event slot count.
+ * @param nslots Number of active event slots.
+ *
+ * This version does not register with a service.
+ */
+IRCUObject::IRCUObject (size_t nslots)
+  : m_svc (nullptr),
+    m_grace (nslots)
+{
+}
+
+
+/**
+ * @brief Destructor.
+ *
+ * Remove this object from the service if it has been registered.
+ */
+IRCUObject::~IRCUObject()
+{
+  if (m_svc && m_svc->remove (this).isFailure())
+    std::abort();
+}
+
+
+} // namespace Athena
diff --git a/Control/AthenaKernel/src/StreamLogger.cxx b/Control/AthenaKernel/src/StreamLogger.cxx
deleted file mode 100644
index a7c04f583ad..00000000000
--- a/Control/AthenaKernel/src/StreamLogger.cxx
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-#include "AthenaKernel/StreamLogger.h"
-
-#include "GaudiKernel/IMessageSvc.h"
-
-#include <stdexcept>
-#include <fstream>
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Constructor for a file
-
-StreamLogger::StreamLogger(const std::string& file): m_isMine(1), 
-						     p_ost(0), p_msgStr(0),
-                                                     m_level (MSG::INFO)
-{
-  m_name = "file:" + file;
-  p_ost = new std::ofstream(file.c_str());
-  if (p_ost == 0) {
-    throw std::invalid_argument("can't open file");
-  }
-}
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Constructor for MsgStream
-
-StreamLogger::StreamLogger(IMessageSvc *svc, MSG::Level lev, 
-			   const std::string& msgName): 
-  m_isMine(1), p_ost(0), p_msgStr(0) {
-  p_msgStr = new MsgStream( svc, msgName);
-  m_level = lev;
-  m_name = "MsgStream";
-}
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Constructor for an ostream
-
-StreamLogger::StreamLogger(std::ostream& ost): m_isMine(0) , p_ost(0), 
-					       p_msgStr(0),
-                                               m_level (MSG::INFO)
-{
-  p_ost = &ost;
-  if (&ost == &std::cerr) {
-    m_name = "STDERR";
-  } else if ( &ost == &std::cout) {
-    m_name = "STDOUT";
-  } else {
-    m_name = "unknown ostream";
-  }
-}
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Destructor
-
-StreamLogger::~StreamLogger() {
-  if (m_isMine && p_ost != 0) {
-    delete p_ost;
-  }
-  if (p_msgStr != 0) {
-    delete p_msgStr;
-  }
-}
diff --git a/Control/AthenaKernel/test/IRCUSvc_test.cxx b/Control/AthenaKernel/test/IRCUSvc_test.cxx
new file mode 100644
index 00000000000..c376a7c7f03
--- /dev/null
+++ b/Control/AthenaKernel/test/IRCUSvc_test.cxx
@@ -0,0 +1,73 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file  IRCUOSVC_test.cxx
+ * @author scott snyder <snyder@bnl.gov>
+ * @date Aug, 2016
+ * @brief Regression tests for RCUObject.
+ */
+
+#undef NDEBUG
+
+#include "AthenaKernel/IRCUSvc.h"
+#include <cassert>
+#include <iostream>
+#include <cstdlib>
+
+
+using Athena::IRCUSvc;
+using Athena::IRCUObject;
+using Athena::RCUObject;
+using Athena::RCURead;
+
+
+class TestRCUSvc
+  : public IRCUSvc
+{
+public:
+  virtual StatusCode remove (IRCUObject* /*obj*/) override { return StatusCode::SUCCESS; }
+  virtual size_t getNumSlots() const override { return 1; }
+  virtual void add (IRCUObject* obj) override
+  { m_added = obj; }
+
+  virtual unsigned long addRef() override { std::abort(); }
+  virtual unsigned long release() override { std::abort(); }
+  virtual StatusCode queryInterface(const InterfaceID &/*ti*/, void** /*pp*/) override { std::abort(); }
+
+  IRCUObject* m_added = nullptr;
+};
+
+
+struct Payload
+{
+  Payload (int a, int b) : 
+    m_a(a), m_b(b)
+  {}
+  Payload& operator= (const Payload&) = default;
+
+  int m_a;
+  int m_b;
+};
+
+
+void test1()
+{
+  std::cout << "test1\n";
+  TestRCUSvc svc;
+  assert (svc.m_added == nullptr);
+  std::unique_ptr<RCUObject<Payload> > obj = svc.newrcu<Payload> (10, 20);
+  RCURead<Payload> r (*obj);
+  assert (r->m_a == 10);
+  assert (r->m_b == 20);
+  assert (svc.m_added == obj.get());
+}
+
+
+int main()
+{
+  test1();
+  return 0;
+}
diff --git a/Control/AthenaKernel/test/RCUObject_test.cxx b/Control/AthenaKernel/test/RCUObject_test.cxx
new file mode 100644
index 00000000000..fa78f31619f
--- /dev/null
+++ b/Control/AthenaKernel/test/RCUObject_test.cxx
@@ -0,0 +1,265 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file  RCUObject_test.cxx
+ * @author scott snyder <snyder@bnl.gov>
+ * @date Aug, 2016
+ * @brief Regression tests for RCUObject.
+ */
+
+#undef NDEBUG
+
+#include "AthenaKernel/RCUObject.h"
+#include "AthenaKernel/IRCUSvc.h"
+#include "boost/thread/shared_mutex.hpp"
+#include "boost/thread/shared_lock_guard.hpp"
+#include <cassert>
+#include <iostream>
+#include <thread>
+#include <mutex>
+#include <atomic>
+
+
+using Athena::IRCUObject;
+using Athena::RCUObject;
+using Athena::IRCUSvc;
+using Athena::RCURead;
+using Athena::RCUReadQuiesce;
+using Athena::RCUUpdate;
+
+
+const int nslots = 4;
+
+
+class TestRCUSvc
+  : public IRCUSvc
+{
+public:
+  virtual StatusCode remove (IRCUObject* obj) override
+  {
+    m_removed = obj;
+    return StatusCode::SUCCESS;
+  }
+  virtual size_t getNumSlots() const override
+  { return nslots; }
+  virtual void add (IRCUObject* /*obj*/) override
+  { }
+
+  virtual unsigned long addRef() override { std::abort(); }
+  virtual unsigned long release() override { std::abort(); }
+  virtual StatusCode queryInterface(const InterfaceID &/*ti*/, void** /*pp*/) override { std::abort(); }
+
+  IRCUObject* m_removed = nullptr;
+};
+
+
+struct Payload
+{
+  Payload (int x=0)
+    : a(x), b(x), c(x), d(x)
+  {
+    ++ninstance;
+  }
+  Payload& operator= (const Payload&) = default;
+  ~Payload()
+  {
+    --ninstance;
+    if (dolog) {
+      std::lock_guard<std::mutex> g (m_mutex);
+      m_dlog.push_back(a);
+    }
+  }
+  static
+  std::vector<int> getlog()
+  {
+    std::lock_guard<std::mutex> g (m_mutex);
+    std::vector<int> log;
+    log.swap (m_dlog);
+    return log;
+  }
+  void check(int x) const
+  {
+    assert (a == x);
+    assert (b == x);
+    assert (c == x);
+    assert (d == x);
+  }
+  void check() const
+  {
+    check(a);
+  }
+  int a, b, c, d;
+
+  static std::atomic<int> ninstance;
+  static bool dolog;
+
+private:
+  static std::vector<int> m_dlog;
+  static std::mutex m_mutex;
+};
+
+std::atomic<int> Payload::ninstance;
+bool Payload::dolog = true;
+std::vector<int> Payload::m_dlog;
+std::mutex Payload::m_mutex;
+
+
+void test1()
+{
+  std::cout << "test1\n";
+
+  TestRCUSvc svc;
+  {
+    RCUObject<Payload>* optr = nullptr;
+    {
+      RCUObject<Payload> rcuo (svc, 3);
+      RCURead<Payload> r (rcuo);
+      r->check(3);
+      
+      optr = &rcuo;
+      assert (svc.m_removed == nullptr);
+    }
+    assert (svc.m_removed == optr);
+  }
+  Payload::getlog();
+}
+
+
+void test2()
+{
+  std::cout << "test2\n";
+  TestRCUSvc svc;
+
+
+  RCUObject<Payload> rcuo (svc);
+  {
+    RCURead<Payload> r (rcuo);
+    r->check(0);
+  }
+  {
+    EventContext ctx (0, 1);
+    RCUUpdate<Payload> u (rcuo, ctx);
+    u->check(0);
+    u.update (std::make_unique<Payload> (2));
+    u->check(2);
+  }
+  {
+    RCURead<Payload> r (rcuo);
+    r->check(2);
+  }
+  {
+    EventContext ctx (0, 2);
+    RCUReadQuiesce<Payload> r (rcuo, ctx);
+    r->check(2);
+  }
+  assert (Payload::getlog().empty());
+  rcuo.quiescent (EventContext (0, 0));
+  assert (Payload::getlog().empty());
+  Gaudi::Hive::setCurrentContextId(3);
+  rcuo.quiescent ();
+  assert (Payload::getlog() == std::vector<int>{0});
+}
+
+
+class ThreadedTest
+{
+public:
+  ThreadedTest (TestRCUSvc& svc);
+  void runtest();
+
+  struct testThread
+  {
+    testThread (ThreadedTest& test, int iworker)
+      : m_test(test), m_iworker(iworker) {}
+    void operator()();
+
+    ThreadedTest& m_test;
+    int m_iworker;
+  };
+
+private:
+  boost::shared_mutex m_sm;
+  RCUObject<Payload> m_rcuobj;
+};
+
+
+ThreadedTest::ThreadedTest (TestRCUSvc& svc)
+  : m_rcuobj(svc)
+{
+}
+
+void ThreadedTest::runtest()
+{
+  std::thread threads[nslots];
+  m_sm.lock();
+  for (int i=0; i < nslots; i++)
+    threads[i] = std::thread (testThread (*this, i));
+  // Try to get the threads starting as much at the same time as possible.
+  m_sm.unlock();
+  for (int i=0; i < nslots; i++)
+    threads[i].join();
+  for (int i=0; i < nslots; i++)
+    m_rcuobj.quiescent (EventContext (0, i));
+}
+
+
+void ThreadedTest::testThread::operator()()
+{
+  boost::shared_lock_guard<boost::shared_mutex> guard (m_test.m_sm);
+  Gaudi::Hive::setCurrentContextId (m_iworker);
+
+  for (int i=0; i < 10000; i++) {
+    if (i%5 == 0) {
+      auto r = m_test.m_rcuobj.reader();
+      r->check();
+    }
+    else if (i%29 == 0) {
+      if (i%2 == 0) {
+        auto r = m_test.m_rcuobj.readerQuiesce (EventContext (0, m_iworker));
+        r->check();
+      }
+      else {
+        auto r = m_test.m_rcuobj.readerQuiesce();
+        r->check();
+      }
+    }
+    else if (i%17 == 0) {
+      EventContext ctx (0, m_iworker);
+      RCUObject<Payload>::Update_t u (m_test.m_rcuobj, ctx);
+      u.update (std::make_unique<Payload> (u->a));
+    }
+
+    if (i%13 == 0)
+      m_test.m_rcuobj.quiescent (EventContext (0, m_iworker));
+  }
+}
+
+
+void test3()
+{
+  std::cout << "test3\n";
+
+  Payload::dolog = false;
+  assert (Payload::ninstance == 0);
+  {
+    TestRCUSvc svc;
+    ThreadedTest test (svc);
+    for (int i=0; i < 1000; i++)
+      test.runtest();
+    assert (Payload::ninstance == 1);
+  }
+  assert (Payload::ninstance == 0);
+}
+
+
+int main()
+{
+  test1();
+  test2();
+  test3();
+  return 0;
+}
+
diff --git a/Control/AthenaKernel/test/errorcheck_test.cxx b/Control/AthenaKernel/test/errorcheck_test.cxx
index 1e74c90adf3..a57eac03b8c 100644
--- a/Control/AthenaKernel/test/errorcheck_test.cxx
+++ b/Control/AthenaKernel/test/errorcheck_test.cxx
@@ -163,7 +163,7 @@ StatusCode test1()
     msg << "a... ";
     msg << "b";
   }
-  REPORT_MESSAGE_WITH_CONTEXT (MSG::INFO, "alg") << "foo" << endreq;
+  REPORT_MESSAGE_WITH_CONTEXT (MSG::INFO, "alg") << "foo" << endmsg;
   assert( test1a().isFailure() );
   assert( test1b().isFailure() );
   assert( test1c().isFailure() );
@@ -195,7 +195,7 @@ void test2 (std::vector<int> = std::vector<int>(),
             int (*)() = 0,
             int [] = 0)
 {
-  REPORT_MESSAGE_WITH_CONTEXT (MSG::INFO, "test2") << "test2" << endreq;
+  REPORT_MESSAGE_WITH_CONTEXT (MSG::INFO, "test2") << "test2" << endmsg;
 
   assert (errorcheck::clean_allocator ("void test2(std::vector<int, std::allocator<int> >, const int*, int (*)(), int*)") ==
           "void test2(std::vector<int>, const int*, int (*)(), int*)");
@@ -204,7 +204,7 @@ void test2 (std::vector<int> = std::vector<int>(),
 
 void test3 (const std::string& = "", int = 0)
 {
-  REPORT_MESSAGE_WITH_CONTEXT (MSG::INFO, "test3") << "test3" << endreq;
+  REPORT_MESSAGE_WITH_CONTEXT (MSG::INFO, "test3") << "test3" << endmsg;
 }
 
 
diff --git a/Control/AthenaKernel/utils/genCLIDDB.cxx b/Control/AthenaKernel/utils/genCLIDDB.cxx
deleted file mode 100644
index ff9970d4fae..00000000000
--- a/Control/AthenaKernel/utils/genCLIDDB.cxx
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-
-#include <cassert>
-#include <exception>
-#include <iostream>
-#include <string>
-#include "TestTools/initGaudi.h"
-#include "GaudiKernel/IClassManager.h"
-#include "GaudiKernel/IProperty.h"
-#include "GaudiKernel/ISvcLocator.h"
-#include "GaudiKernel/SmartIF.h"
-#include "AthenaKernel/IClassIDSvc.h"
-#ifdef ATLAS_CMAKE
-#include <dlfcn.h>
-#endif
-
-#include <boost/program_options.hpp>
-namespace po = boost::program_options;
-
-using namespace std;
-using namespace Athena_test;
-
-int inputError(std::string errDescr, const po::options_description& optDescr ) {
-  cerr << errDescr << "\n" << optDescr << endl;
-  return 1;
-}
-int gaudiError(std::string errDescr) {
-  cerr << errDescr << endl;
-  return 2;
-}
-
-int main(int argc, char* argv[]) {
-  // Declare the supported options.
-  po::options_description desc("clidDB_gen allowed options");
-  desc.add_options()
-    ("help,h", "produce help message")
-    ("package,p", po::value<string>(), "package we want to load clids from")
-    ("input,i", po::value<string>(), "optional path to input clid db file")
-    ("output,o", po::value<string>(), "optional path to resulting clid db file")
-    ("jobopts,j", po::value<string>(), "name of optional job options txt file, located at ../share/jobopts")
-    ;
-  string packageName("ALL");
-  string inputCLIDDB;
-  string outFileName;
-
-  po::variables_map vm;
-  try {
-    po::store(po::parse_command_line(argc, argv, desc), vm);
-    po::notify(vm);    
-  } catch (const exception& e) {
-    return inputError(e.what(), desc);
-  }
-
-  if (vm.count("help")) {
-    cout << desc << endl;
-    return 0;
-  }
-  
-  if (vm.count("package")) {
-    cout << "Generating clid.db for package " 
-	 << vm["package"].as<string>() << ".\n";
-    packageName = vm["package"].as<string>();
-  } else {
-    return inputError("Please specify a package using option --package.\n", 
-		      desc);
-  }
-
-  if (vm.count("output")) {
-    outFileName = vm["output"].as<string>();
-  } else {
-    outFileName = packageName + "_clid.db";
-  }
-  cout << "Resulting clid.db will be written to " 
-       << outFileName << ".\n";
-
-  ISvcLocator* pSvcLoc(0);
-  if (vm.count("jobopts")) { 
-    if (!initGaudi(vm["jobopts"].as<string>(), pSvcLoc)) {
-      return gaudiError("clidDB_gen can not run");
-    }  
-  } else {
-    if (!initGaudi(pSvcLoc)) {
-      return gaudiError("clidDB_gen can not run");
-    }  
-  }
-  if ( 0 == pSvcLoc ) {
-    return gaudiError( "NULL pointer to ISvcLocator" );
-  }
-  SmartIF<IClassManager> pICM(pSvcLoc);
-  if (!pICM.isValid()) {
-    gaudiError("can not get IClassManager");
-  }
-
-#ifdef ATLAS_CMAKE
-  dlopen("libCLIDComps.so", RTLD_LAZY);
-#endif
-  IClassIDSvc* pClassIDSvc(0);
-  if (!(pSvcLoc->service("ClassIDSvc", pClassIDSvc, true).isSuccess())) {
-    cerr << "can not get ClassIDSvc, no clid.db will be generated" << endl;
-    return 0;
-  }
-  if ( 0 == pClassIDSvc ) {
-    return gaudiError("NULL pointer to IClassIDSvc");
-  }
-
-  IProperty *pCLIDSvcProp(dynamic_cast<IProperty*>(pClassIDSvc));
-  if ( 0 == pCLIDSvcProp ) {
-    return gaudiError("NULL pointer to IClassIDSvc's property");
-  }
-
-  if (vm.count("input")) {
-    cout << "Reading clid.db from " 
-	 << vm["input"].as<string>() << ".\n";
-    if (!(pCLIDSvcProp->setProperty( "CLIDDBFiles", 
-				     "{\"" + vm["input"].as<string>() + "\"}" )).isSuccess()) {
-      return inputError("Error setting ClassIDSvc.CLIDDBFiles to " 
-			+ vm["input"].as<string>(), 
-			desc);
-    }
-  }
-
-  pCLIDSvcProp->setProperty( "OutputFileName", outFileName );
-
-  if (!pICM->loadModule(packageName).isSuccess()) {
-    return gaudiError("can not load module " + packageName);
-  }
-
-  //fill clid db
-  if (!(pClassIDSvc->reinitialize()).isSuccess()) {
-    return gaudiError("can not reinitialize ClassIDSvc");
-  }
-
-  //write out merged clid db on service finalize
-  return (pClassIDSvc->finalize()).isSuccess() ? 0 : -1;
-}
-- 
GitLab