Skip to content
Snippets Groups Projects
Commit 69ea047a authored by Walter Lampl's avatar Walter Lampl
Browse files

Merge branch 'setCachedValue.CxxUtils-20181018' into 'master'

CxxUtils: Make sure value is valid after CachedValue::set() returns.

See merge request atlas/athena!15129

Former-commit-id: c5adf35a
parents cee27b1c de7aab52
No related branches found
No related tags found
No related merge requests found
// This file's extension implies that it's C, but it's really -*- C++ -*-. // 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$ // $Id$
/** /**
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "CxxUtils/checker_macros.h" #include "CxxUtils/checker_macros.h"
#include "CxxUtils/stall.h"
#include <atomic> #include <atomic>
#include <utility> #include <utility>
...@@ -42,7 +43,8 @@ enum CacheState { ...@@ -42,7 +43,8 @@ enum CacheState {
* store() method; however, this is not atomic and should not be done while * 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 * 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. * 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: * The state of the cached value is given by m_cacheState, which can have the values:
* INVALID: No value has been cached. * INVALID: No value has been cached.
...@@ -94,11 +96,13 @@ public: ...@@ -94,11 +96,13 @@ public:
/// Set the value, assuming it is currently invalid. /// Set the value, assuming it is currently invalid.
/// Otherwise, this method will do nothing. /// Otherwise, this method will do nothing.
/// The value will be valid once this returns.
void set (const T& val) const; void set (const T& val) const;
/// Set the value by move, assuming it is currently invalid. /// Set the value by move, assuming it is currently invalid.
/// Otherwise, this method will do nothing. /// Otherwise, this method will do nothing.
/// The value will be valid once this returns.
void set (T&& val) const; void set (T&& val) const;
...@@ -108,7 +112,8 @@ public: ...@@ -108,7 +112,8 @@ public:
/// Return a pointer to the cached value. /// 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; const T* ptr() const;
......
// $Id$ /*
* Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration.
*/
/** /**
* @file CxxUtils/CachedValue.icc * @file CxxUtils/CachedValue.icc
* @author scott snyder <snyder@bnl.gov> * @author scott snyder <snyder@bnl.gov>
...@@ -169,6 +171,7 @@ struct CacheLock ...@@ -169,6 +171,7 @@ struct CacheLock
/** /**
* @brief Set the value, assuming it is currently invalid. * @brief Set the value, assuming it is currently invalid.
* Otherwise, this method will do nothing. * Otherwise, this method will do nothing.
* The value will be valid once this returns.
*/ */
template <class T> template <class T>
inline inline
...@@ -181,6 +184,12 @@ void CachedValue<T>::set (const T& val) const ...@@ -181,6 +184,12 @@ void CachedValue<T>::set (const T& val) const
if (lock) { if (lock) {
m_val = val; 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 ...@@ -188,6 +197,7 @@ void CachedValue<T>::set (const T& val) const
/** /**
* @brief Set the value by move, assuming it is currently invalid. * @brief Set the value by move, assuming it is currently invalid.
* Otherwise, this method will do nothing. * Otherwise, this method will do nothing.
* The value will be valid once this returns.
*/ */
template <class T> template <class T>
inline inline
...@@ -200,6 +210,12 @@ void CachedValue<T>::set (T&& val) const ...@@ -200,6 +210,12 @@ void CachedValue<T>::set (T&& val) const
if (lock) { if (lock) {
m_val = std::move (val); 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 ...@@ -215,14 +231,17 @@ bool CachedValue<T>::isValid() const
CacheState stat; CacheState stat;
// Get the state flag. // Get the state flag.
// Spin if another thread is currently updating. // Spin if another thread is currently updating.
while ((stat = m_cacheValid) == UPDATING) ; while ((stat = m_cacheValid) == UPDATING) {
CxxUtils::stall();
}
return stat == VALID; return stat == VALID;
} }
/** /**
* @brief Return a pointer to the cached value. * @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> template <class T>
inline inline
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment