diff --git a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/CMakeLists.txt b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/CMakeLists.txt
index cf7e9856a6fc2db628bd78c85d2699da2bf2a9bf..a93efe5c8d32cc993e4972303682ef6e17229d34 100644
--- a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/CMakeLists.txt
+++ b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/CMakeLists.txt
@@ -14,6 +14,6 @@ atlas_add_library( LArReadoutGeometry
                    PUBLIC_HEADERS LArReadoutGeometry
                    PRIVATE_INCLUDE_DIRS ${Boost_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS}
                    PRIVATE_DEFINITIONS ${CLHEP_DEFINITIONS}
-                   LINK_LIBRARIES ${GEOMODELCORE_LIBRARIES} AthenaKernel GeoPrimitives Identifier LArHV StoreGateLib SGtests
+                   LINK_LIBRARIES ${GEOMODELCORE_LIBRARIES} AthenaKernel GeoPrimitives Identifier LArHV StoreGateLib SGtests CxxUtils
                    PRIVATE_LINK_LIBRARIES ${Boost_LIBRARIES} ${CLHEP_LIBRARIES} GeoModelUtilities GaudiKernel RDBAccessSvcLib GeoModelInterfaces )
 
diff --git a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/LArReadoutGeometry/ATLAS_CHECK_THREAD_SAFETY b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/LArReadoutGeometry/ATLAS_CHECK_THREAD_SAFETY
new file mode 100644
index 0000000000000000000000000000000000000000..a2444725738108320d56ed966ad59aa2a73225c0
--- /dev/null
+++ b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/LArReadoutGeometry/ATLAS_CHECK_THREAD_SAFETY
@@ -0,0 +1 @@
+LArCalorimeter/LArGeoModel/LArReadoutGeometry
diff --git a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/LArReadoutGeometry/EMBCell.h b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/LArReadoutGeometry/EMBCell.h
index 4d038850377bbee14116693e47c2fd314a00b506..ea88b4ee6621355dac2d55812166d945ee12cc64 100755
--- a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/LArReadoutGeometry/EMBCell.h
+++ b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/LArReadoutGeometry/EMBCell.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 #ifndef LARREADOUTGEOMETRY_EMBCELL_H
@@ -8,10 +8,10 @@
 #include "LArReadoutGeometry/EMBDetDescr.h"
 #include "LArReadoutGeometry/EMBHVPathologies.h"
 #include "LArHV/EMBHVElectrode.h"
-#include <cmath>
 #include "GeoModelKernel/RCBase.h"
+#include "CxxUtils/CachedValue.h"
+#include <cmath>
 #include <vector>
-#include <mutex>
 
 class EMBPresamplerHVModule;
 
@@ -174,29 +174,29 @@ class EMBCell : public RCBase
 
       const EMBDetDescr *m_embDetDescr;
 
-      // The cell does NOT own the pointers to its electrodes
-      mutable std::vector<const EMBHVElectrode*> m_electrode;
-
-      mutable const EMBPresamplerHVModule* m_presamplerModule{nullptr};
+      struct HVInfo
+      {
+        // The cell does NOT own the pointers to its electrodes
+        std::vector<const EMBHVElectrode*> m_electrode;
+        const EMBPresamplerHVModule* m_presamplerModule = nullptr;
+      };
+      CxxUtils::CachedValue<HVInfo> m_hvinfo;
 
-      mutable std::vector<EMBHVPathologiesConstLink> m_hvPathologies;
+      std::vector<EMBHVPathologiesConstLink> m_hvPathologies;
 
       unsigned int m_clockwork;
 
       friend class ImaginaryFriend;
 
-      void initHV() const;
-
-      mutable std::mutex m_mut;
-
-      mutable bool m_initHVdone;
+      const HVInfo& getHVInfo() const;
+      void initHV (HVInfo& hvinfo) const;
 };
 
 
 // Class EMBCell 
 
 inline EMBCell::EMBCell (unsigned int side, const EMBDetDescr *embDescriptor, unsigned int eta, unsigned int phi)
-  :m_embDetDescr(embDescriptor),m_clockwork(phi | (eta<<8) | (side <<17) ), m_initHVdone(false)
+  :m_embDetDescr(embDescriptor),m_clockwork(phi | (eta<<8) | (side <<17) )
 {
 }
 
diff --git a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/LArReadoutGeometry/EMBDetectorManager.h b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/LArReadoutGeometry/EMBDetectorManager.h
index c9a5d238544d76133686dee35b198a236045ef72..4d17023b3a3d4ca4a463b858346edb216be5135f 100755
--- a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/LArReadoutGeometry/EMBDetectorManager.h
+++ b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/LArReadoutGeometry/EMBDetectorManager.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 #ifndef LARREADOUTGEOMETRY_EMBDETECTORMANAGER_H
@@ -10,6 +10,7 @@
 #include "LArReadoutGeometry/EMBAccordionDetails.h"
 #include "LArHV/EMBHVManager.h"
 #include "LArHV/EMBPresamplerHVManager.h"
+#include "CxxUtils/CachedUniquePtr.h"
 
 class EMBDetDescr;
 class EMBDetectorRegion;
@@ -129,8 +130,8 @@ class EMBDetectorManager : public GeoVDetectorManager
    *	by this manager.
    */
   EMBDetRegionArray             m_DetRegionsRandom;
-  const EMBBasicReadoutNumbers* m_basicReadoutNumbers;
-  mutable EMBAccordionDetails*  m_accordionDetails;
+  std::unique_ptr<const EMBBasicReadoutNumbers>  m_basicReadoutNumbers;
+  CxxUtils::CachedUniquePtr<EMBAccordionDetails> m_accordionDetails;
   const EMBHVManager&           m_hvManager;
   const EMBPresamplerHVManager& m_presamplerHVManager;
 };
@@ -138,15 +139,16 @@ class EMBDetectorManager : public GeoVDetectorManager
 
 inline const EMBAccordionDetails * EMBDetectorManager::getAccordionDetails () const
 {
-
-  if (!m_accordionDetails) m_accordionDetails = new EMBAccordionDetails();
-  return m_accordionDetails;
+  if (!m_accordionDetails) {
+    m_accordionDetails.set (std::make_unique<EMBAccordionDetails>());
+  }
+  return m_accordionDetails.get();
 }
 
 
 inline const EMBBasicReadoutNumbers * EMBDetectorManager::getBasicReadoutNumbers () const
 {
-  return m_basicReadoutNumbers;
+  return m_basicReadoutNumbers.get();
 }
 
 
diff --git a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/LArReadoutGeometry/EMECCell.h b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/LArReadoutGeometry/EMECCell.h
index 845b97d6d03bd5433d2275440f07d36669dbffab..943559bce7326d3083900cd62a8ae5b153f72365 100755
--- a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/LArReadoutGeometry/EMECCell.h
+++ b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/LArReadoutGeometry/EMECCell.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 #ifndef LARREADOUTGEOMETRY_EMECCELL_H
@@ -11,7 +11,7 @@
 #include "GeoModelKernel/RCBase.h"
 #include "LArHV/EMECHVElectrode.h"
 #include "LArHV/EMECPresamplerHVModule.h"
-#include <mutex>
+#include "CxxUtils/CachedValue.h"
 
 /**
  * @class EMECCell
@@ -154,22 +154,21 @@ class EMECCell : public RCBase
 
   const EMECDetDescr *m_emecDetDescr;
 
-  // The cell does NOT own the pointers to its electrodes
-  mutable std::vector<const EMECHVElectrode*> m_electrode;
-
-  mutable const EMECPresamplerHVModule* m_presamplerModule{nullptr};
+  struct HVInfo
+  {
+    // The cell does NOT own the pointers to its electrodes
+    std::vector<const EMECHVElectrode*> m_electrode;
+    const EMECPresamplerHVModule* m_presamplerModule = nullptr;
+  };
+  CxxUtils::CachedValue<HVInfo> m_hvinfo;
 
   unsigned int m_clockwork;
 
 
   friend class ImaginaryFriend;
 
-  void initHV() const;
-
-  mutable std::mutex m_mut;
-
-  mutable bool m_initHVdone;
-  
+  const HVInfo& getHVInfo() const;
+  void initHV (HVInfo& hvinfo) const;
 };
 
 
@@ -177,7 +176,7 @@ class EMECCell : public RCBase
 
 inline EMECCell::EMECCell (unsigned int endcap, const EMECDetDescr *emecDescriptor, unsigned int eta, unsigned int phi)
   // 8 bits are needed for phi index, 6 for eta, 1 for endcap.
- :m_emecDetDescr(emecDescriptor),m_clockwork(phi | (eta<<8) | (endcap <<15) ),m_initHVdone(false)
+ :m_emecDetDescr(emecDescriptor),m_clockwork(phi | (eta<<8) | (endcap <<15) )
 {
   
 }
diff --git a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/LArReadoutGeometry/EMECDetectorManager.h b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/LArReadoutGeometry/EMECDetectorManager.h
index db4816965916c2eb3871661674434b8e5134bc20..a7798cb39ad26887bbe7176d488ca075ee67c4ff 100755
--- a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/LArReadoutGeometry/EMECDetectorManager.h
+++ b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/LArReadoutGeometry/EMECDetectorManager.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 #ifndef LARREADOUTGEOMETRY_EMECDETECTORMANAGER_H
@@ -8,6 +8,7 @@
 #include "GeoModelKernel/GeoVDetectorManager.h"
 #include "LArHV/EMECHVManager.h"
 #include "LArHV/EMECPresamplerHVManager.h"
+#include "CxxUtils/CachedPointer.h"
 class EMECDetDescr;
 class EMECDetectorRegion;
 
@@ -239,9 +240,9 @@ class EMECDetectorManager : public GeoVDetectorManager
   /**
    * @brief 	The HV Managers for the emec;
    */
-  mutable const EMECHVManager* m_HVManager[2];
+  CxxUtils::CachedPointer<const EMECHVManager> m_HVManager[2];
 
-  mutable const EMECPresamplerHVManager* m_presamplerHVManager;
+  CxxUtils::CachedPointer<const EMECPresamplerHVManager> m_presamplerHVManager;
 };
 
 /**
diff --git a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/LArReadoutGeometry/FCALModule.h b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/LArReadoutGeometry/FCALModule.h
index 010f745fc0c4d31dd21b23b82d25c7d4e06ad926..33c4ec37fc090e9151fd33835ee1693ee30170d2 100755
--- a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/LArReadoutGeometry/FCALModule.h
+++ b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/LArReadoutGeometry/FCALModule.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 #ifndef LARREADOUTGEOMETRY_FCALMODULE_H
@@ -11,6 +11,8 @@
 #include "GeoModelKernel/GeoDefinitions.h"
 #include "GaudiKernel/SystemOfUnits.h"
 #include "GeoPrimitives/GeoPrimitives.h"
+#include "CxxUtils/CachedValue.h"
+#include <utility>
 
 class FCALDetectorManager;
 
@@ -121,6 +123,7 @@ class FCALModule : public GeoVDetectorElement
   double getProjectivityDisplacement() const;
       
   private:
+      static constexpr size_t MAXTUBES = 64;
     
       FCALModule(const FCALModule &right);
       FCALModule & operator=(const FCALModule &right);
@@ -152,14 +155,12 @@ class FCALModule : public GeoVDetectorElement
       FCALDetectorManager* m_manager;
       
       /**
-       * @brief A vector that holds the list of tile sizes.
+       * @brief X/Y pairs of tile sizes.
        */
-      mutable std::vector<double> m_TileSizeX;
-      
-      /**
-       * @brief A vector that holds the list of tile sizes.
-       */
-      mutable std::vector<double> m_TileSizeY;
+      using tubexy_t = std::pair<double, double>;
+      CxxUtils::CachedValue<tubexy_t> m_tileSizes[MAXTUBES];
+
+      const tubexy_t& getFullWidths (unsigned int ntubes) const;
       
       /**
        * @brief Holds Delta Z,  Full width of a cell
diff --git a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/LArReadoutGeometry/FCALTile.h b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/LArReadoutGeometry/FCALTile.h
index f36f8f0b5bbfcf3b3f518380c5e80e5a1533f4f1..6383b99f7adab2e28fe28130b162a08951fd87bb 100755
--- a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/LArReadoutGeometry/FCALTile.h
+++ b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/LArReadoutGeometry/FCALTile.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 #ifndef LARREADOUTGEOMETRY_FCALTILE_H
@@ -8,6 +8,8 @@
 #include "LArReadoutGeometry/FCAL_ChannelMap.h"
 #include "LArHV/FCALHVModule.h"
 #include "LArReadoutGeometry/FCALTubeConstLink.h"
+#include "CxxUtils/CachedPointer.h"
+#include "CxxUtils/CachedValue.h"
 
 class FCALModule;
 
@@ -112,12 +114,12 @@ class FCALTile
   /**
    * @brief	Cache of subgaps.
    */
-  mutable const FCALHVLine* m_line[4] = { nullptr };
+  CxxUtils::CachedPointer<const FCALHVLine> m_line[4];
 
   /**
    * @brief	Cache of tubes.
    */
-  mutable std::vector<FCALTubeConstLink> m_tube;
+  CxxUtils::CachedValue<std::vector<FCALTubeConstLink> > m_tube;
 
   
       
diff --git a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/LArReadoutGeometry/FCAL_ChannelMap.h b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/LArReadoutGeometry/FCAL_ChannelMap.h
index 5193bc525e46edb0d968c9e8d7ba53f2de92595b..073c533a8f8b208f136d0b2005e964ea1b050b4e 100755
--- a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/LArReadoutGeometry/FCAL_ChannelMap.h
+++ b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/LArReadoutGeometry/FCAL_ChannelMap.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 // ***************************************************************************
@@ -149,14 +149,21 @@ public:
     
 
 private:
+    float x1(int isam, 
+             int eta, 
+             int phi) const;
+    float y1(int isam, 
+             int eta, 
+             int phi) const;
+
     /** Geometrical parameters here, in CLHEP::cm please to be compatible with G3 */
     static const double m_tubeSpacing[];
     double 		m_tubeDx[3];
     double 		m_tubeDy[3];
     double 		m_tileDx[3];
     double 		m_tileDy[3];
-    mutable bool	m_invert_x;   // Some geometry need x inverted
-    mutable bool	m_invert_xy;  // Some geometry need xy crossed 
+    bool		m_invert_x;   // Some geometry need x inverted
+    bool		m_invert_xy;  // Some geometry need xy crossed 
     
     tileMap_t   	                        m_tileMap[3];
     void                                        create_tileMap( int isam );
diff --git a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/LArReadoutGeometry/GeoStraightAccSection.h b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/LArReadoutGeometry/GeoStraightAccSection.h
index c70b041be0f667b5f01e959818c7ef99cfae9bee..4ce253960913bb883ab69959a8d790711e18fa0c 100644
--- a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/LArReadoutGeometry/GeoStraightAccSection.h
+++ b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/LArReadoutGeometry/GeoStraightAccSection.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 #ifndef LARREADOUTGEOMETRY_GEOSTRAIGHTACCSECTION_H
@@ -56,7 +56,7 @@ class GeoStraightAccSection {
  private:
 
   class Clockwork;
-  Clockwork *m_c;
+  std::unique_ptr<Clockwork> m_c;
 
   GeoStraightAccSection (const GeoStraightAccSection&);
   GeoStraightAccSection& operator= (const GeoStraightAccSection&);
diff --git a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/LArReadoutGeometry/GeoStraightAccSection.icc b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/LArReadoutGeometry/GeoStraightAccSection.icc
index b3ec9459387501a8744f4da1abb6a55fc4cc5bf7..43f3d4aa3d6ae71c249f9cb4ece6f5c4c7a00a2e 100644
--- a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/LArReadoutGeometry/GeoStraightAccSection.icc
+++ b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/LArReadoutGeometry/GeoStraightAccSection.icc
@@ -1,20 +1,19 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
+#include "CxxUtils/CachedUniquePtr.h"
 #include <stdexcept>
 class GeoStraightAccSection::Clockwork {
 
 public:
 
-  Clockwork():r1(NULL),r2(NULL){};
+  Clockwork():r1(NULL){};
 
   ~Clockwork() { 
   }
 
-  void buildFastCache();
   void buildSmallCache();
-  void fillFastCache();
 
 
   class Rep1 {
@@ -33,14 +32,19 @@ public:
 
   public:
 
-    GeoXF::Function *transfunction[14];
+    std::unique_ptr<GeoXF::Function> transfunction[14];
     double           halfLength[14];
   };
 
-  mutable Rep1 *r1;
-  mutable Rep2 *r2;
+  CxxUtils::CachedUniquePtrT<Rep1> r1;
+  std::unique_ptr<Rep2> r2;
+
+  const Rep1& getFastCache() const;
+  Rep1& getWritableFastCache();
+  Rep2& getWritableSmallCache();
 
 private:
+  void fillFastCache (Rep1& rep1) const;
   
   Clockwork( const Clockwork &); 
 
@@ -48,29 +52,59 @@ private:
 };
 
 
+inline
+const GeoStraightAccSection::Clockwork::Rep1&
+GeoStraightAccSection::Clockwork::getFastCache() const
+{
+  if (!r1) {
+    auto rep = std::make_unique<Rep1>();
+    fillFastCache (*rep);
+    r1.set (std::move (rep));
+  }
+  return *r1.get();
+}
+
+
+inline
+GeoStraightAccSection::Clockwork::Rep1&
+GeoStraightAccSection::Clockwork::getWritableFastCache()
+{
+  if (r2) throw std::runtime_error("Error in GeoStraightAccSection: Illegal Modification Sequence");
+  if (!r1) {
+    r1.store (std::make_unique<Rep1>());
+  }
+  return *r1.get();
+}
+
+
+inline
+GeoStraightAccSection::Clockwork::Rep2&
+GeoStraightAccSection::Clockwork::getWritableSmallCache()
+{
+  if (r1) throw std::runtime_error("Error in GeoStraightAccSection: Illegal Modification Sequence");
+  if (!r2) buildSmallCache();
+  return *r2;
+}
+
+
 inline const double & GeoStraightAccSection::XCent(int stackid, int cellid)   const
 {
-  if (!m_c->r1) m_c->fillFastCache();
-  return m_c->r1->xcent[stackid][cellid];
+  return m_c->getFastCache().xcent[stackid][cellid];
 }
 inline const double & GeoStraightAccSection::YCent(int stackid, int cellid)   const
 {
-  if (!m_c->r1) m_c->fillFastCache();
-  return m_c->r1->ycent[stackid][cellid];
+  return m_c->getFastCache().ycent[stackid][cellid];
 }
 inline const double & GeoStraightAccSection::Sinu(int stackid, int cellid)       const
 {
-  if (!m_c->r1) m_c->fillFastCache();
-  return m_c->r1->sinu[stackid][cellid];
+  return m_c->getFastCache().sinu[stackid][cellid];
 }
 inline const double & GeoStraightAccSection::Cosu(int stackid, int cellid)       const
 {
-  if (!m_c->r1) m_c->fillFastCache();
-  return m_c->r1->cosu[stackid][cellid];
+  return m_c->getFastCache().cosu[stackid][cellid];
 }
 inline const double & GeoStraightAccSection::HalfLength(int stackid, int cellid)   const
 {
-  if (!m_c->r1) m_c->fillFastCache();
-  return m_c->r1->halfLength[stackid][cellid];
+  return m_c->getFastCache().halfLength[stackid][cellid];
 }
 
diff --git a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/LArReadoutGeometry/HECCell.h b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/LArReadoutGeometry/HECCell.h
index a7907e758d1c8c851625c0477481bddcaf12d126..370eb0934f1858b2f19ae091760fb72f63d763ea 100755
--- a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/LArReadoutGeometry/HECCell.h
+++ b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/LArReadoutGeometry/HECCell.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 #ifndef LARREADOUTGEOMETRY_HECCELL_H
@@ -9,6 +9,7 @@
 #include "GeoModelKernel/CellBinning.h"
 #include "GeoModelKernel/RCBase.h"
 #include "LArHV/HECHVSubgap.h"
+#include "CxxUtils/CachedValue.h"
 #include <mutex>
 
 /**
@@ -193,19 +194,15 @@ class HECCell : public RCBase
   /**
    * @brief	Cache of subgaps.
    */
-  mutable std::vector<const HECHVSubgap*> m_subgap;
+  CxxUtils::CachedValue<std::vector<const HECHVSubgap*> > m_subgaps;
 
   /**
    * @brief Additional Implementation Declarations
    */
   friend class ImaginaryFriend;
 
-  void initHV() const;
-
-  mutable std::mutex m_mut;
-
-  mutable bool m_initHVdone;
-
+  const std::vector<const HECHVSubgap*>& getSubgaps() const;
+  void initHV (std::vector<const HECHVSubgap*>& subgaps) const;
 };
 
 
@@ -216,7 +213,7 @@ inline HECCell::HECCell (unsigned int endcap, const HECDetDescr *hecDescriptor,
   
   
   
-  :m_hecDetDescr(hecDescriptor),m_clockwork(phi | (eta<<6) | (endcap <<10)), m_initHVdone(false)
+  :m_hecDetDescr(hecDescriptor),m_clockwork(phi | (eta<<6) | (endcap <<10))
   
 {
   
diff --git a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/EMBAccordionDetails.cxx b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/EMBAccordionDetails.cxx
index 1a34066cddd63cf37d7b3a856581be50992ba92e..f53b0416065194038ee4cb4cb658eb0b66c3ca0d 100644
--- a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/EMBAccordionDetails.cxx
+++ b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/EMBAccordionDetails.cxx
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 #include "LArReadoutGeometry/EMBAccordionDetails.h"
@@ -299,7 +299,7 @@ const GeoStraightAccSection *EMBAccordionDetails::getAbsorberSections() const {
     ISvcLocator* svcLocator = Gaudi::svcLocator(); 
     StoreGateSvc *detStore;
 
-    const DataHandle<GeoStraightAccSection> sa(NULL);
+    const GeoStraightAccSection* sa = nullptr;
 
     status = svcLocator->service ("DetectorStore",detStore);
     if (status != StatusCode::SUCCESS) throw std::runtime_error ("Cannot locate Storegate");
@@ -322,7 +322,7 @@ const GeoStraightAccSection *EMBAccordionDetails::getElectrodeSections() const {
     ISvcLocator* svcLocator = Gaudi::svcLocator(); 
     StoreGateSvc *detStore;
 
-    const DataHandle<GeoStraightAccSection> sa(NULL);
+    const GeoStraightAccSection* sa = nullptr;
 
     status = svcLocator->service ("DetectorStore",detStore);
     if (status != StatusCode::SUCCESS) throw std::runtime_error ("Cannot locate Storegate");
diff --git a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/EMBCell.cxx b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/EMBCell.cxx
index 807758dd840e03f3a44d822e4942b71d08855949..72bd1f3256bc6341f51867e7f31843e276af9ee8 100755
--- a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/EMBCell.cxx
+++ b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/EMBCell.cxx
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 #include "LArReadoutGeometry/EMBCell.h"
@@ -26,30 +26,31 @@ double EMBCell::getPhiLocalUpper(double /*r*/) const {
 }
 
 unsigned int EMBCell::getNumElectrodes() const {
-  //if (m_electrode.size()==0 && !m_presamplerModule) initHV();
-  if(!m_initHVdone) initHV();
-  return m_electrode.size();
+  return getHVInfo().m_electrode.size();
 }
 
 const EMBHVElectrode & EMBCell::getElectrode (unsigned int i) const {
-  //if (m_electrode.size()==0 && !m_presamplerModule) initHV();
-  if(!m_initHVdone) initHV();
-  return *(m_electrode[i]);
+  return *getHVInfo().m_electrode[i];
 }
 
 const EMBPresamplerHVModule& EMBCell::getPresamplerHVModule () const {
-  //if (m_electrode.size()==0 && !m_presamplerModule) initHV();
-  if(!m_initHVdone) initHV();
-  return *m_presamplerModule;
+  return *getHVInfo().m_presamplerModule;
 }
 
 
-void EMBCell::initHV() const {
-
-  if(m_initHVdone) return; // should be done only once
+const EMBCell::HVInfo& EMBCell::getHVInfo() const
+{
+  if (!m_hvinfo.isValid()) {
+    HVInfo hvinfo;
+    initHV (hvinfo);
+    m_hvinfo.set (std::move (hvinfo));
+  }
+  return *m_hvinfo.ptr();
+}
 
-  std::lock_guard<std::mutex> lock(m_mut);
 
+void EMBCell::initHV (HVInfo& hvinfo) const
+{
   if (getSamplingIndex()==0) {
     const EMBPresamplerHVManager& presamplerHVManager=getDescriptor()->getManager()->getPresamplerHVManager();
     double phiUpper = getPhiMaxNominal();
@@ -72,7 +73,7 @@ void EMBCell::initHV() const {
     if (iEta==lastDivision) throw std::runtime_error ("Error in EMBCell:  Presampler HV not found");
 
     unsigned int iSide=getEndcapIndex();
-    m_presamplerModule = &(presamplerHVManager.getHVModule(iSide,iEta,iPhi));
+    hvinfo.m_presamplerModule = &(presamplerHVManager.getHVModule(iSide,iEta,iPhi));
 
   }
   else {
@@ -105,11 +106,10 @@ void EMBCell::initHV() const {
     
     for (unsigned int iElectrode=iOffset;iElectrode<iOffset+N;iElectrode++) {
       const EMBHVElectrode& hvElec = hvMod.getElectrode(iElectrode);
-      m_electrode.push_back(&hvElec);
+      hvinfo.m_electrode.push_back(&hvElec);
     }
     
   }
-  m_initHVdone=true;
 } 
 
 
diff --git a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/EMBDetDescr.cxx b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/EMBDetDescr.cxx
index 543b5fdb943776c8dcb463e6fc55b30f595502d7..791d1c20c75067a2925fbad94a5d47c05175e7bd 100755
--- a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/EMBDetDescr.cxx
+++ b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/EMBDetDescr.cxx
@@ -1,20 +1,30 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 #include "LArReadoutGeometry/EMBDetDescr.h"
 #include "LArReadoutGeometry/EMBBasicReadoutNumbers.h"
 #include "LArReadoutGeometry/EMBDetectorManager.h"
 #include "GeoModelKernel/CellBinning.h"
+
+
+namespace {
+  
+
 struct Boundary {
   double min;
   double max;
   unsigned int nDiv;
   unsigned int firstDiv;
-} etaBoundariesBarrel [4][2] = {{{0.000, 1.525,  61,0},{0.000, 0.000,  0,0}},    // 
+};
+
+const Boundary
+etaBoundariesBarrel [4][2] = {{{0.000, 1.525,  61,0},{0.000, 0.000,  0,0}},    // 
 				{{0.003125, 1.400, 447,1},{1.400, 1.475,  3,0}},    // 
 				{{0.000, 1.400,  56,0},{1.400, 1.475,  1,0}},    // 
-				{{0.000, 1.350,  27,0},{0.000, 0.000,  0,0}}};   // 
+				{{0.000, 1.350,  27,0},{0.000, 0.000,  0,0}}};   //
+
+} // anonymous namespace
 
 
  
diff --git a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/EMBDetectorManager.cxx b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/EMBDetectorManager.cxx
index cbfe87f0a0f9562b9ab0dc48f0ac5fb2eb9a18ea..4bfbb88246b4f55920ac656759c53fde7c718adc 100755
--- a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/EMBDetectorManager.cxx
+++ b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/EMBDetectorManager.cxx
@@ -29,7 +29,8 @@ public:
 
 EMBDetectorManager::EMBDetectorManager(const EMBHVManager& hvManager
 				       , const EMBPresamplerHVManager& presamplerHVManager)
-  : m_hvManager(hvManager)
+  : m_basicReadoutNumbers (std::make_unique<EMBBasicReadoutNumbers>())
+  , m_hvManager(hvManager)
   , m_presamplerHVManager(presamplerHVManager)
 {
   setName("LArEMB");
@@ -42,10 +43,6 @@ EMBDetectorManager::EMBDetectorManager(const EMBHVManager& hvManager
       }
     } 
   }
-
-
-  m_basicReadoutNumbers = new EMBBasicReadoutNumbers();
-  m_accordionDetails    = NULL;
 }
 
 
@@ -53,8 +50,6 @@ EMBDetectorManager::~EMBDetectorManager()
 {
   for (unsigned int i=0;i<getNumDetectorRegions();i++) delete m_DetRegionsIterative[i];
   for (unsigned int i=0;i<getNumTreeTops();i++) getTreeTop(i)->unref();
-  delete m_basicReadoutNumbers;
-  delete m_accordionDetails;
 }
 
 
diff --git a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/EMECCell.cxx b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/EMECCell.cxx
index 39193e4e88aed0e99d422c33aa770aae2c206561..3864fa1bd396f761230186b42fe108224ce03003 100755
--- a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/EMECCell.cxx
+++ b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/EMECCell.cxx
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 #include "LArReadoutGeometry/EMECCell.h"
@@ -16,29 +16,31 @@ EMECCell::~EMECCell()
 }
 
 unsigned int EMECCell::getNumElectrodes() const {
-  //if (m_electrode.size()==0 && !m_presamplerModule) initHV();
-  if(!m_initHVdone) initHV();
-  return m_electrode.size();
+  return getHVInfo().m_electrode.size();
 }
 
 const EMECHVElectrode& EMECCell::getElectrode (unsigned int i) const {
-  //if ((m_electrode.size()==0 || m_electrode[i] == nullptr) && !m_presamplerModule) initHV();
-  if(!m_initHVdone) initHV();
-  return *(m_electrode[i]);
+  return *getHVInfo().m_electrode[i];
 }
 
 const EMECPresamplerHVModule& EMECCell::getPresamplerHVModule () const {
-  //if (m_electrode.size()==0 && !m_presamplerModule) initHV();
-  if(!m_initHVdone) initHV();
-  return *m_presamplerModule;
+  return *getHVInfo().m_presamplerModule;
 }
 
-void EMECCell::initHV() const {
 
-  if(m_initHVdone) return; // should be done only once
+const EMECCell::HVInfo& EMECCell::getHVInfo() const
+{
+  if (!m_hvinfo.isValid()) {
+    HVInfo hvinfo;
+    initHV (hvinfo);
+    m_hvinfo.set (std::move (hvinfo));
+  }
+  return *m_hvinfo.ptr();
+}
 
-  std::lock_guard<std::mutex> lock(m_mut);
 
+void EMECCell::initHV (HVInfo& hvinfo) const
+{
   if (getSamplingIndex()==0) {
     const EMECPresamplerHVManager& presamplerHVManager=getDescriptor()->getManager()->getPresamplerHVManager();
     double phiUpper = getPhiMaxNominal();
@@ -48,7 +50,7 @@ void EMECCell::initHV() const {
     const CellBinning * phiBinning=presamplerHVManager.getPhiBinning();
     unsigned int iPhi = int((phi - phiBinning->getStart())/phiBinning->getDelta()) + phiBinning->getFirstDivisionNumber();
     unsigned int iSide=getEndcapIndex();
-    m_presamplerModule = &(presamplerHVManager.getHVModule(iSide,iPhi));
+    hvinfo.m_presamplerModule = &(presamplerHVManager.getHVModule(iSide,iPhi));
 
   }
   else {
@@ -97,11 +99,10 @@ void EMECCell::initHV() const {
     //std::cout <<   " hvMod << " << hvMod << std::endl;
     for (unsigned int iElectrode=iOffset;iElectrode<iOffset+NE;iElectrode++) {
       const EMECHVElectrode& hvElec = hvMod.getElectrode(iElectrode);
-      m_electrode.push_back(&hvElec);
+      hvinfo.m_electrode.push_back(&hvElec);
     }
     
   } 
-  m_initHVdone = true;
 }
 
 
diff --git a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/EMECDetDescr.cxx b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/EMECDetDescr.cxx
index 8ed210b57c1075f3f51d57d548a8459875ee5a57..1c55d4d0d926e0b1c5bc8bd5e70d78f23905872f 100755
--- a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/EMECDetDescr.cxx
+++ b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/EMECDetDescr.cxx
@@ -1,10 +1,14 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 #include "LArReadoutGeometry/EMECDetectorManager.h"
 #include "LArReadoutGeometry/EMECDetDescr.h"
 
+
+namespace {
+
+
 /** 
  * @brief An internal class which is none of your business
  **/
@@ -13,7 +17,9 @@ struct Boundary {
   double min;
   double max;
   unsigned int nDiv;
-} etaBoundariesEndcap[4][2][6] = {{{{1.500, 1.800, 12},{0.000, 0.000,  0},{0.000, 0.000,  0},{0.000, 0.000,  0},{0.000, 0.000,  0},{0.000, 0.000,  0}},    // presampler outer
+};
+const Boundary
+etaBoundariesEndcap[4][2][6] = {{{{1.500, 1.800, 12},{0.000, 0.000,  0},{0.000, 0.000,  0},{0.000, 0.000,  0},{0.000, 0.000,  0},{0.000, 0.000,  0}},    // presampler outer
 				   {{0.000, 0.000,  0},{0.000, 0.000,  0},{0.000, 0.000,  0},{0.000, 0.000,  0},{0.000, 0.000,  0},{0.000, 0.000,  0}}},   // presampler inner
 				  {{{1.375, 1.425,  1},{1.425, 1.500,  3},{1.500, 1.800, 96},{1.800, 2.000, 48},{2.000, 2.400, 64},{2.400, 2.500,  4}},    // sample 1 outer 
 				   {{2.500, 3.200,  7},{0.000, 0.000,  0},{0.000, 0.000,  0},{0.000, 0.000,  0},{0.000, 0.000,  0},{0.000, 0.000,  0}}},   // sample 1 inner
@@ -22,6 +28,10 @@ struct Boundary {
 				  {{{1.500, 2.500, 20},{0.000, 0.000,  0},{0.000, 0.000,  0},{0.000, 0.000,  0},{0.000, 0.000,  0},{0.000, 0.000,  0}},    // sample 3 outer
 				   {{0.000, 0.000,  0},{0.000, 0.000,  0},{0.000, 0.000,  0},{0.000, 0.000,  0},{0.000, 0.000,  0},{0.000, 0.000,  0}}}};  // sample 3 inner
 
+
+} // anonymous namespace
+
+
 EMECDetDescr::EMECDetDescr (const EMECDetectorManager *detManager
 			    , unsigned int sampling
 			    , unsigned int region
diff --git a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/EMECDetectorManager.cxx b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/EMECDetectorManager.cxx
index fb7efdf627ce75f40df80e89570deafe2dc33f72..7ef593befa744d502846814c8ccca8770527da14 100755
--- a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/EMECDetectorManager.cxx
+++ b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/EMECDetectorManager.cxx
@@ -38,8 +38,8 @@ EMECDetectorManager::EMECDetectorManager(const EMECHVManager* hvManagerInner
     }
   }
 
-  m_HVManager[0]=hvManagerInner;
-  m_HVManager[1]=hvManagerOuter;
+  m_HVManager[0].store (hvManagerInner);
+  m_HVManager[1].store (hvManagerOuter);
 
   // The EMEC gets and managers certain arrays needed to build descriptors.  Here is that:
   ISvcLocator *svcLocator = Gaudi::svcLocator();
@@ -129,25 +129,25 @@ void EMECDetectorManager::addTreeTop (PVLink treeTop)
 
 const EMECHVManager& EMECDetectorManager::getHVManager (EMECHVManager::IOType io) const
 {
-  if(!m_HVManager[io]) {
+  if(!m_HVManager[io].get()) {
     //Support lazy initialization for testbeams
     ServiceHandle<StoreGateSvc> detStore ("DetectorStore", "HECHVManager");
     const LArHVManager *manager{nullptr};
     if (detStore->retrieve(manager)==StatusCode::SUCCESS) {
-      m_HVManager[io]=&(manager->getEMECHVManager(io));
+      m_HVManager[io].set (&(manager->getEMECHVManager(io)));
     }
   }
-  return *(m_HVManager[io]);
+  return *(m_HVManager[io].get());
 }
 
 const EMECPresamplerHVManager& EMECDetectorManager::getPresamplerHVManager () const
 {
-  if (!m_presamplerHVManager) {
+  if (!m_presamplerHVManager.get()) {
     ServiceHandle<StoreGateSvc> detStore ("DetectorStore", "HECHVManager");
     const LArHVManager *manager{nullptr};
     if (detStore->retrieve(manager)==StatusCode::SUCCESS) {
-      m_presamplerHVManager=&(manager->getEMECPresamplerHVManager());
+      m_presamplerHVManager.set (&(manager->getEMECPresamplerHVManager()));
     }
   } 
-  return *m_presamplerHVManager;
+  return *m_presamplerHVManager.get();
 }
diff --git a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/EMECDetectorRegion.cxx b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/EMECDetectorRegion.cxx
index b2587ffbec7bb3f9a49b66227250b798c04d86e3..ca45e94ccb2c1fc06ecf86355214150723ac3dfc 100755
--- a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/EMECDetectorRegion.cxx
+++ b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/EMECDetectorRegion.cxx
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 #include "GeoModelKernel/GeoVFullPhysVol.h"
@@ -51,7 +51,7 @@ HepGeom::Point3D<double> EMECDetectorRegion::getRefPlanePos () const
   if (shape->typeID()!=GeoPcon::getClassTypeID()) {
     throw std::runtime_error ("EMECDetectorRegion cannot compute absolute position of reference plane");
   }
-  GeoPcon *pcon = (GeoPcon *) shape;
+  const GeoPcon *pcon = static_cast<const GeoPcon *> (shape);
   HepGeom::Point3D<double> center(0,0,pcon->getZPlane(0)-m_descriptor->getManager()->getRefToActive());
   return (Amg::EigenTransformToCLHEP(physVol->getAbsoluteTransform())*center);
 }
diff --git a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/FCALModule.cxx b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/FCALModule.cxx
index ab5f93bdbb3fae5cb9c4cd4d40ce0573e8276f76..aca1b74716350b5a4bd46a6254e9c67b6eb7639e 100755
--- a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/FCALModule.cxx
+++ b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/FCALModule.cxx
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 #include "LArReadoutGeometry/FCAL_ChannelMap.h"
@@ -80,38 +80,12 @@ FCALModule::Module FCALModule::getModuleIndex () const
 
 double FCALModule::getFullWidthX (const FCALTile& tile) const
 {
-  double newVal=0.0;
-  unsigned int ntubes = tile.getNumTubes();
-  if (m_TileSizeX.size()<ntubes) {
-    m_TileSizeX.resize(ntubes,newVal);
-    m_TileSizeY.resize(ntubes,newVal);
-  }
-  if (m_TileSizeX[ntubes-1]==newVal) {
-    const FCAL_ChannelMap *cMap=m_manager->getChannelMap();
-    float dx,dy;
-    cMap->tileSize(m_Mod,ntubes,dx,dy);
-    m_TileSizeX[ntubes-1]=dx;
-    m_TileSizeY[ntubes-1]=dy;
-  }
-  return m_TileSizeX[ntubes-1];
+  return getFullWidths (tile.getNumTubes()).first;
 }
 
 double FCALModule::getFullWidthY (const FCALTile& tile) const
 {
-  double newVal=0.0;
-  unsigned int ntubes = tile.getNumTubes();
-  if (m_TileSizeY.size()<ntubes) {
-    m_TileSizeX.resize(ntubes,newVal);
-    m_TileSizeY.resize(ntubes,newVal);
-  }
-  if (m_TileSizeY[ntubes-1]==newVal) {
-    const FCAL_ChannelMap *cMap=m_manager->getChannelMap();
-    float dx,dy;
-    cMap->tileSize(m_Mod,ntubes,dx,dy);
-    m_TileSizeX[ntubes-1]=dx;
-    m_TileSizeY[ntubes-1]=dy;
-  }
-  return m_TileSizeY[ntubes-1];
+  return getFullWidths (tile.getNumTubes()).second;
 }
 
 double FCALModule::getFullDepthZ (const FCALTile& ) const
@@ -153,3 +127,16 @@ void FCALModule::setManager (FCALDetectorManager* fcalManager)
   std::sort(m_tileList.begin(),m_tileList.end());
 }
 
+
+const FCALModule::tubexy_t&
+FCALModule::getFullWidths (unsigned int ntubes) const
+{
+  if (ntubes > MAXTUBES) std::abort();
+  if (!m_tileSizes[ntubes-1].isValid()) {
+    const FCAL_ChannelMap *cMap=m_manager->getChannelMap();
+    float dx,dy;
+    cMap->tileSize(m_Mod,ntubes,dx,dy);
+    m_tileSizes[ntubes-1].set (std::make_pair (dx, dy));
+  }
+  return *m_tileSizes[ntubes-1].ptr();
+}
diff --git a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/FCALTile.cxx b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/FCALTile.cxx
index 34c3717d95c9206d98478124fde2d8e0aad9a53f..cf72e8d3c239cda2eaba71a01009880b0c3c08de 100755
--- a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/FCALTile.cxx
+++ b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/FCALTile.cxx
@@ -79,23 +79,25 @@ unsigned int FCALTile::getNumHVLines() const {
 }
 
 const FCALHVLine* FCALTile::getHVLine (unsigned int i) const {
-  if (!m_line[i]) {
+  if (!m_line[i].get()) {
     
     for (unsigned int j=0;j<getNumTubes();j++) {
       unsigned int index=getTube(j)->getHVLine().getLineIndex();
       if (i==index) { 
-	m_line[i]=&(getTube(j)->getHVLine());
+	m_line[i].set (&(getTube(j)->getHVLine()));
 	break;
       }
     }
   }
-  return m_line[i];
+  return m_line[i].get();
 }
 
 
 FCALTubeConstLink FCALTile::getTube (unsigned int i) const {
 
-  if (m_tube.size()==0) {
+  if (!m_tube.isValid()) {
+
+    std::vector<FCALTubeConstLink> tube;
 
     //std::cout << " in FCALTile::getTube " << std::endl;
     // Then go to storegate..
@@ -169,9 +171,10 @@ FCALTubeConstLink FCALTile::getTube (unsigned int i) const {
 	
 	FCALTubeConstLink tubeLink(new FCALTube(this, hvElec, (*t).second.x(),(*t).second.y()));
 	
-	m_tube.push_back(tubeLink);
+	tube.push_back(tubeLink);
       }
     }
+    m_tube.set (std::move (tube));
   }
-  return m_tube[i];
+  return (*m_tube.ptr())[i];
 }
diff --git a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/FCAL_ChannelMap.cxx b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/FCAL_ChannelMap.cxx
index 4bb9cbd7d353071c022cff0eb9baf7a5d5200479..ab8811975366fd591ff2f64554a50393e24815ac 100755
--- a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/FCAL_ChannelMap.cxx
+++ b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/FCAL_ChannelMap.cxx
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 // ***************************************************************************
@@ -305,13 +305,15 @@ FCAL_ChannelMap::getTileID(int isam, float x_orig, float y_orig,
 float 
 FCAL_ChannelMap::x(int isam, int eta, int phi) const
 {
-  if(m_invert_xy){ 
-   // temp turn off the flag 
-   m_invert_xy=false; 
-   float y1 =  y(isam,eta,phi); 
-   m_invert_xy=true; 
-   return y1; 
-  } 
+  if(m_invert_xy) { 
+    return y1(isam,eta,phi); 
+  }
+  return x1 (isam, eta, phi);
+}
+
+float 
+FCAL_ChannelMap::x1(int isam, int eta, int phi) const
+{
   float x;
 
   tileName_t tilename = (eta << 16) + phi  ; 
@@ -348,15 +350,14 @@ float
 FCAL_ChannelMap::y(int isam, int eta, int phi) const
 {
   if(m_invert_xy){
-
-   // temp turn off the flag 
-   m_invert_xy=false; 
-   float x1 =  x(isam,eta,phi); 
-   m_invert_xy=true; 
-   return x1; 
-
+    return x1(isam,eta,phi); 
   }
+  return y1 (isam, eta, phi);
+}
 
+float 
+FCAL_ChannelMap::y1(int isam, int eta, int phi) const
+{
   float y;
 
   tileName_t tilename = (eta << 16) + phi  ; 
diff --git a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/GeoStraightAccSection.cxx b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/GeoStraightAccSection.cxx
index 2ba99e25d806d6d132469158c97a1aa64c58d5c4..ec0bb691200e1d0fcb1e8de606ec5042490522ae 100644
--- a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/GeoStraightAccSection.cxx
+++ b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/GeoStraightAccSection.cxx
@@ -1,30 +1,31 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 #include "LArReadoutGeometry/GeoStraightAccSection.h"
-void GeoStraightAccSection::Clockwork::buildFastCache() {
-  delete r1;
-  r1=new Rep1();
-}
-
-void GeoStraightAccSection::Clockwork::buildSmallCache() {
-  if (r2) for (int i=0;i<14;i++) delete r2->transfunction[i]; 
-  delete r2;
-  r2=new Rep2();
-  for (int i=0;i<14;i++) r2->transfunction[i]=0;
+void GeoStraightAccSection::Clockwork::buildSmallCache()
+{
+  if (!r2) {
+    r2 = std::make_unique<Rep2>();
+  }
+  else {
+    for (int i=0;i<14;i++) {
+      r2->halfLength[i] = 0;
+      r2->transfunction[i].reset();
+    }
+  }
 }
 
-void GeoStraightAccSection::Clockwork::fillFastCache() {
-  if (!r1) buildFastCache();
+void GeoStraightAccSection::Clockwork::fillFastCache (Rep1& rep1) const
+{
   for (int i=0;i<1024;i++) {
     for (int j=0;j<14; j++) {
       GeoTrf::Transform3D XF = (*r2->transfunction[j])(i);
-      r1->xcent[i][j] = XF(0,3); //dx
-      r1->ycent[i][j] = XF(1,3); //dy
-      r1->cosu [i][j] = -XF(0,1);//xy
-      r1->sinu [i][j] = XF(0,2);//xz
-      r1->halfLength[i][j]= r2->halfLength[j];
+      rep1.xcent[i][j] = XF(0,3); //dx
+      rep1.ycent[i][j] = XF(1,3); //dy
+      rep1.cosu [i][j] = -XF(0,1);//xy
+      rep1.sinu [i][j] = XF(0,2);//xz
+      rep1.halfLength[i][j]= r2->halfLength[j];
     }
   }
 }
@@ -32,58 +33,41 @@ void GeoStraightAccSection::Clockwork::fillFastCache() {
 // Modifiers
 double & GeoStraightAccSection::XCent(int stackid, int cellid) 
 {
-  if (m_c->r2) throw std::runtime_error("Error in GeoStraightAccSection: Illegal Modification Sequence");
-  if (!m_c->r1) m_c->buildFastCache();
-  return m_c->r1->xcent[stackid][cellid];
+  return m_c->getWritableFastCache().xcent[stackid][cellid];
 }
 double & GeoStraightAccSection::YCent(int stackid, int cellid) 
 {
-  if (m_c->r2) throw std::runtime_error("Error in GeoStraightAccSection: Illegal Modification Sequence");
-  if (!m_c->r1) m_c->buildFastCache();
-  return m_c->r1->ycent[stackid][cellid];
+  return m_c->getWritableFastCache().ycent[stackid][cellid];
 }
 double & GeoStraightAccSection::Cosu(int stackid, int cellid)
 {
-  if (m_c->r2) throw std::runtime_error("Error in GeoStraightAccSection: Illegal Modification Sequence");
-  if (!m_c->r1) m_c->buildFastCache();
-  return m_c->r1->cosu[stackid][cellid];
+  return m_c->getWritableFastCache().cosu[stackid][cellid];
 }
 double & GeoStraightAccSection::Sinu(int stackid, int cellid)
 {
-  if (m_c->r2) throw std::runtime_error("Error in GeoStraightAccSection: Illegal Modification Sequence");
-  if (!m_c->r1) m_c->buildFastCache();
-  return m_c->r1->sinu[stackid][cellid];
+  return m_c->getWritableFastCache().sinu[stackid][cellid];
 }
 double  & GeoStraightAccSection::HalfLength(int stackid, int cellid)
 {
-  if (m_c->r2) throw std::runtime_error("Error in GeoStraightAccSection: Illegal Modification Sequence");
-  if (!m_c->r1)m_c->buildFastCache();
-  return m_c->r1->halfLength[stackid][cellid];
+  return m_c->getWritableFastCache().halfLength[stackid][cellid];
 }
 
 
 void GeoStraightAccSection::setHalfLength(int stackid, double halfLength) {
-  if (m_c->r1) throw std::runtime_error("Error in GeoStraightAccSection: Illegal Modification Sequence");
-  if (!m_c->r2) m_c->buildSmallCache();
-  m_c->r2->halfLength[stackid]=halfLength;
+  m_c->getWritableSmallCache().halfLength[stackid]=halfLength;
 }
 
 void GeoStraightAccSection::setTransform(int stackid, GeoXF::TRANSFUNCTION f) {
-  if (m_c->r1) throw std::runtime_error("Error in GeoStraightAccSection: Illegal Modification Sequence");
-  if (!m_c->r2) m_c->buildSmallCache();
-  delete m_c->r2->transfunction[stackid];
-  m_c->r2->transfunction[stackid]=f.clone();
+  m_c->getWritableSmallCache().transfunction[stackid] =
+    std::unique_ptr<GeoXF::Function> (f.clone());
 }
 
-GeoStraightAccSection::GeoStraightAccSection():m_c(new Clockwork) {
-  m_c->r1=NULL;
-  m_c->r2=NULL;
+GeoStraightAccSection::GeoStraightAccSection()
+  : m_c(std::make_unique<Clockwork>())
+{
 }	
 
-GeoStraightAccSection::~GeoStraightAccSection() {
-  if (m_c->r2) for (int i=0;i<14;i++) delete m_c->r2->transfunction[i];
-  delete m_c->r2;
-  delete m_c->r1;
-  delete m_c;
+GeoStraightAccSection::~GeoStraightAccSection()
+{
 }
 
diff --git a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/HECCell.cxx b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/HECCell.cxx
index e18b5ff8b196686ecb87068c14bc875ee81011e3..853eb1184af055e4b1c4a8328131207f7568bb8f 100755
--- a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/HECCell.cxx
+++ b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/HECCell.cxx
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 #include "LArReadoutGeometry/HECCell.h"
@@ -13,24 +13,28 @@ HECCell::~HECCell()
 
 
 unsigned int HECCell::getNumSubgaps() const {
-  //if (m_subgap.size()==0) initHV();
-  if(!m_initHVdone) initHV();
-  return m_subgap.size();
+  return getSubgaps().size();
 }
 
 const HECHVSubgap& HECCell::getSubgap (unsigned int i) const {
-  //if (m_subgap.size()==0) initHV();
-  if(!m_initHVdone) initHV();
-  return *(m_subgap[i]);
+  return *getSubgaps()[i];
 }
 
-void HECCell::initHV() const {
 
-  if(m_initHVdone) return; // should be done only once
-
-  std::lock_guard<std::mutex> lock(m_mut);
+const std::vector<const HECHVSubgap*>&
+HECCell::getSubgaps() const
+{
+  if (!m_subgaps.isValid()) {
+    std::vector<const HECHVSubgap*> subgaps;
+    initHV (subgaps);
+    m_subgaps.set (std::move (subgaps));
+  }
+  return *m_subgaps.ptr();
+}
 
 
+void HECCell::initHV (std::vector<const HECHVSubgap*>& subgaps) const
+{
   const HECHVManager& hvManager=getDescriptor()->getManager()->getHVManager();
 
 
@@ -47,9 +51,8 @@ void HECCell::initHV() const {
   const HECHVModule& hvMod = hvManager.getHVModule(iSide,iPhi,iSampling);
   for (unsigned int iSubgap=0;iSubgap<4;iSubgap++) {
     const HECHVSubgap& hvElec = hvMod.getSubgap(iSubgap);
-    m_subgap.push_back(&hvElec);
+    subgaps.push_back(&hvElec);
   }
-  m_initHVdone=true;
 } 
 
 
diff --git a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/HECDetectorRegion.cxx b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/HECDetectorRegion.cxx
index e1d196f4820ef23fb8630ac991b326891d8d8f87..484cc4adad2619cd176391f74f391d7d3192464e 100755
--- a/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/HECDetectorRegion.cxx
+++ b/LArCalorimeter/LArGeoModel/LArReadoutGeometry/src/HECDetectorRegion.cxx
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 #include "LArReadoutGeometry/HECDetectorRegion.h"
@@ -76,7 +76,7 @@ HepGeom::Point3D<double> HECDetectorRegion::getRefPlanePos () const
   if (shape->typeID()!=GeoPcon::getClassTypeID()) {
     throw std::runtime_error ("HECDetectorRegion cannot compute absolute position of reference plane");
   }
-  GeoPcon *pcon = (GeoPcon *) shape;
+  const GeoPcon *pcon = static_cast<const GeoPcon *> (shape);
   HepGeom::Point3D<double> center(0,0,pcon->getZPlane(0));
   return (Amg::EigenTransformToCLHEP(physVol->getAbsoluteTransform())*center);
 }