diff --git a/Control/CxxUtils/CxxUtils/CachedValue.h b/Control/CxxUtils/CxxUtils/CachedValue.h
index b8ad327a2b096baf6eeb6acaf21784919e23cc81..7e9fb71698177a628a1df3735962db50c8f00b99 100644
--- a/Control/CxxUtils/CxxUtils/CachedValue.h
+++ b/Control/CxxUtils/CxxUtils/CachedValue.h
@@ -1,6 +1,6 @@
 // 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.
+ * Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration.
  */
 // $Id$
 /**
@@ -16,6 +16,7 @@
 
 
 #include "CxxUtils/checker_macros.h"
+#include "CxxUtils/stall.h"
 #include <atomic>
 #include <utility>
 
@@ -42,7 +43,8 @@ enum CacheState {
  * store() method; however, this is not atomic and should not be done while
  * other threads may be accessing the value.)  The validity of the value
  * may be tested with isValid(), and ptr() will get back a pointer to the value.
- * ptr() should not be called until isValid() has returned true.
+ * ptr() should not be called until isValid() has returned true or set()
+ * returned.
  *
  * The state of the cached value is given by m_cacheState, which can have the values:
  *   INVALID:  No value has been cached.
@@ -94,11 +96,13 @@ public:
     
   /// Set the value, assuming it is currently invalid.
   /// Otherwise, this method will do nothing.
+  /// The value will be valid once this returns.
   void set (const T& val) const;
  
 
   /// Set the value by move, assuming it is currently invalid.
   /// Otherwise, this method will do nothing.
+  /// The value will be valid once this returns.
   void set (T&& val) const;
  
 
@@ -108,7 +112,8 @@ public:
     
 
   /// Return a pointer to the cached value.
-  /// Should not be called unless isValid() has returned true.
+  /// Should not be called unless isValid() has returned true or set()
+  /// has returned.
   const T* ptr() const;
 
 
diff --git a/Control/CxxUtils/CxxUtils/CachedValue.icc b/Control/CxxUtils/CxxUtils/CachedValue.icc
index 762dab34d7056562c1da8a236cd9c06b246d6121..af8d0a3a71c0fc98891402fbba7c8208cced8e5a 100644
--- a/Control/CxxUtils/CxxUtils/CachedValue.icc
+++ b/Control/CxxUtils/CxxUtils/CachedValue.icc
@@ -1,4 +1,6 @@
-// $Id$
+/*
+ * Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration.
+ */
 /**
  * @file CxxUtils/CachedValue.icc
  * @author scott snyder <snyder@bnl.gov>
@@ -169,6 +171,7 @@ struct CacheLock
 /**
  * @brief Set the value, assuming it is currently invalid.
  * Otherwise, this method will do nothing.
+ * The value will be valid once this returns.
  */
 template <class T>
 inline
@@ -181,6 +184,12 @@ void CachedValue<T>::set (const T& val) const
     if (lock) {
       m_val = val;
     }
+    else {
+      // Spin if another thread is currently updating.
+      while (m_cacheValid == UPDATING) {
+        CxxUtils::stall();
+      }
+    }
   }
 }
 
@@ -188,6 +197,7 @@ void CachedValue<T>::set (const T& val) const
 /**
  * @brief Set the value by move, assuming it is currently invalid.
  * Otherwise, this method will do nothing.
+ * The value will be valid once this returns.
  */
 template <class T>
 inline
@@ -200,6 +210,12 @@ void CachedValue<T>::set (T&& val) const
     if (lock) {
       m_val = std::move (val);
     }
+    else {
+      // Spin if another thread is currently updating.
+      while (m_cacheValid == UPDATING) {
+        CxxUtils::stall();
+      }
+    }
   }
 }
 
@@ -215,14 +231,17 @@ bool CachedValue<T>::isValid() const
   CacheState stat;
   // Get the state flag.
   // Spin if another thread is currently updating.
-  while ((stat = m_cacheValid) == UPDATING) ;
+  while ((stat = m_cacheValid) == UPDATING) {
+    CxxUtils::stall();
+  }
   return stat == VALID;
 }
 
 
 /**
  * @brief Return a pointer to the cached value.
- *        Should not be called unless isValid() has returned true.
+ *        Should not be called unless isValid() has returned true or set()
+ *        has returned.
  */
 template <class T>
 inline