ATLAS Offline Software
CachedPointer.icc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
3 */
4 // $Id$
5 /**
6  * @file CxxUtils/CachedPointer.icc
7  * @author scott snyder <snyder@bnl.gov>
8  * @date Nov, 2017, from earlier code in AthLinks.
9  * @brief Cached pointer with atomic update.
10  */
11 
12 
13 namespace CxxUtils {
14 
15 
16 /**
17  * @brief Default constructor. Sets the element to null.
18  */
19 template <class T>
20 inline
21 CachedPointer<T>::CachedPointer()
22  : m_a (nullptr)
23 {
24 }
25 
26 
27 /**
28  * @brief Constructor from an element.
29  */
30 template <class T>
31 inline
32 CachedPointer<T>::CachedPointer (pointer_t elt)
33  : m_a (elt)
34 {
35 }
36 
37 
38 /**
39  * @brief Copy constructor.
40  */
41 template <class T>
42 inline
43 CachedPointer<T>::CachedPointer (const CachedPointer& other) noexcept
44  : m_a (other.get())
45 {
46 }
47 
48 /**
49  * @brief Move constructor.
50  */
51 template <class T>
52 inline
53 CachedPointer<T>::CachedPointer ( CachedPointer&& other) noexcept
54  : m_a (other.get())
55 {
56  //Does not own pointer so don't need to null
57 }
58 
59 
60 
61 /**
62  * @brief Assignment.
63  */
64 template <class T>
65 inline
66 CachedPointer<T>&
67 CachedPointer<T>::operator= (const CachedPointer& other)
68 {
69  if (this != &other) {
70  store (other.get());
71  }
72  return *this;
73 }
74 
75 
76 /**
77  * @brief Set the element, assuming it is currently null.
78  * @param elt The new value for the element.
79  *
80  * The current value of the element must either be null, in which case,
81  * it is set to ELT, or else it must already be equal to ELT, in which
82  * case no write occurs. Anything else is considered an error.
83  *
84  * The reason for doing things this way is that we (have to) allow
85  * a pointer to the underlying element to escape to user code, and we
86  * don't want a write to conflict with a non-atomic read. (Such a read
87  * can only happen after the element has been set for the first time.)
88  */
89 template <class T>
90 inline
91 void CachedPointer<T>::set (pointer_t elt) const
92 {
93  // Set the element to ELT if it is currently null.
94  pointer_t null = nullptr;
95  m_a.compare_exchange_strong (null, elt, std::memory_order_relaxed);
96  // If the element was originally null, then NULL will still be null.
97  // If the element was originally ELT, then no write will have been performed,
98  // and NULL will be ELT. If the element was originally something else,
99  // then NULL will be set to that value.
100  assert (null == nullptr || null == elt);
101 }
102 
103 
104 /**
105  * @brief Store a new value to the element.
106  */
107 template <class T>
108 inline
109 void CachedPointer<T>::store (pointer_t elt)
110 {
111  m_a.store (elt, std::memory_order_relaxed);
112 }
113 
114 
115 /**
116  * @brief Return the current value of the element.
117  */
118 template <class T>
119 inline
120 typename CachedPointer<T>::pointer_t
121 CachedPointer<T>::get() const
122 {
123  return m_a.load (std::memory_order_relaxed);
124 }
125 
126 
127 /**
128  * @brief Return a pointer to the cached element.
129  */
130 template <class T>
131 inline
132 const typename CachedPointer<T>::pointer_t*
133 CachedPointer<T>::ptr() const
134 {
135  return &m_e;
136 }
137 
138 
139 } // namespace CxxUtils