ATLAS Offline Software
CachedUniquePtr.icc
Go to the documentation of this file.
1 // This file's extension implies that it's C, but it's really -*- C++ -*-.
2 /*
3  * Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration.
4  */
5 // $Id$
6 /**
7  * @file CxxUtils/CachedUniquePtr.icc
8  * @author scott snyder <snyder@bnl.gov>
9  * @date Mar, 2019
10  * @brief Cached unique_ptr with atomic update.
11  */
12 
13 
14 namespace CxxUtils {
15 
16 
17 /**
18  * @brief Default constructor. Sets the element to null.
19  */
20 template <class T>
21 inline
22 CachedUniquePtrT<T>::CachedUniquePtrT()
23  : m_ptr (nullptr)
24 {
25 }
26 
27 
28 /**
29  * @brief Constructor from an element.
30  */
31 template <class T>
32 inline
33 CachedUniquePtrT<T>::CachedUniquePtrT (std::unique_ptr<T> elt)
34  : m_ptr (elt.release())
35 {
36 }
37 
38 
39 /**
40  * @brief Move constructor.
41  */
42 template <class T>
43 inline
44 CachedUniquePtrT<T>::CachedUniquePtrT (CachedUniquePtrT&& other) noexcept
45  : m_ptr (other.release().release())
46 {
47 }
48 
49 
50 /**
51  * @brief Move.
52  */
53 template <class T>
54 inline
55 CachedUniquePtrT<T>&
56 CachedUniquePtrT<T>::operator= (CachedUniquePtrT&& other) noexcept
57 {
58  if (this != &other) {
59  store (other.release());
60  }
61  return *this;
62 }
63 
64 
65 /**
66  * @brief Destructor.
67  */
68 template <class T>
69 inline
70 CachedUniquePtrT<T>::~CachedUniquePtrT()
71 {
72  delete m_ptr;
73 }
74 
75 
76 /**
77  * @brief Atomically set the element. If already set, then @c elt is discarded.
78  * @param elt The new value for the element.
79  *
80  * If the current value of the element is null, then set it to @c elt.
81  * Otherwise, delete @c elt.
82  * This is done atomically.
83  * Returns the final value of the element.
84  */
85 template <class T>
86 inline
87 T* CachedUniquePtrT<T>::set (std::unique_ptr<T> elt) const
88 {
89  // Set the element to ELT if it is currently null.
90  T* ptr = elt.release();
91  T* expected = nullptr;
92  if (!m_ptr.compare_exchange_strong (expected, ptr)) {
93  // Was already set. Delete the new value.
94  delete ptr;
95  ptr = expected;
96  }
97  return ptr;
98 }
99 
100 
101 /**
102  * @brief Store a new value to the element.
103  * Not compatible with other concurrent access.
104  */
105 template <class T>
106 inline
107 void CachedUniquePtrT<T>::store (std::unique_ptr<T> elt) noexcept
108 {
109  T* old = m_ptr.exchange (elt.release());
110  delete old;
111 }
112 
113 
114 /**
115  * @brief Return the current value of the element.
116  */
117 template <class T>
118 inline
119 T*
120 CachedUniquePtrT<T>::get() const
121 {
122  return m_ptr.load();
123 }
124 
125 
126 /**
127  * @brief Dereference the element.
128  */
129 template <class T>
130 inline
131 T&
132 CachedUniquePtrT<T>::operator*() const
133 {
134  return *get();
135 }
136 
137 
138 /**
139  * @brief Dereference the element.
140  */
141 template <class T>
142 inline
143 T*
144 CachedUniquePtrT<T>::operator->() const
145 {
146  return get();
147 }
148 
149 
150 /**
151  * @brief Test if the element is null.
152  */
153 template <class T>
154 inline
155 CachedUniquePtrT<T>::operator bool() const
156 {
157  return get() != nullptr;
158 }
159 
160 
161 /**
162  * @brief Transfer ownership from the element: return the current value as a
163  * unique_ptr, leaving the element null.
164  */
165 template <class T>
166 inline
167 std::unique_ptr<T>
168 CachedUniquePtrT<T>::release() noexcept
169 {
170  T* old = m_ptr.exchange (nullptr);
171  return std::unique_ptr<T> (old);
172 }
173 
174 
175 } // namespace CxxUtils