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