ATLAS Offline Software
Loading...
Searching...
No Matches
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
13namespace CxxUtils {
14
15template <class T>
16inline
17void CachedPointerStaticAsserts()
18{
19}
20
21
22/**
23 * @brief Default constructor. Sets the element to null.
24 */
25template <class T>
26inline
27CachedPointer<T>::CachedPointer()
28 : m_a (nullptr)
29{
30 static_assert(std::is_nothrow_copy_assignable_v<CachedPointer<T>> &&
31 std::is_nothrow_move_assignable_v<CachedPointer<T>> &&
32 std::is_nothrow_copy_constructible_v<CachedPointer<T>> &&
33 std::is_nothrow_move_constructible_v<CachedPointer<T>>);
34}
35
36/**
37 * @brief Constructor from an element.
38 */
39template <class T>
40inline
41CachedPointer<T>::CachedPointer (pointer_t elt)
42 : m_a (elt)
43{
44 static_assert(std::is_nothrow_copy_assignable_v<CachedPointer<T>> &&
45 std::is_nothrow_move_assignable_v<CachedPointer<T>> &&
46 std::is_nothrow_copy_constructible_v<CachedPointer<T>> &&
47 std::is_nothrow_move_constructible_v<CachedPointer<T>>);
48}
49
50
51/**
52 * @brief Copy constructor.
53 */
54template <class T>
55inline
56CachedPointer<T>::CachedPointer (const CachedPointer& other) noexcept
57 : m_a (other.get())
58{
59}
60
61/**
62 * @brief Assignment.
63 */
64template <class T>
65inline
66CachedPointer<T>&
67CachedPointer<T>::operator= (const CachedPointer& other) noexcept
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 */
89template <class T>
90inline
91void 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 */
107template <class T>
108inline
109void 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 */
118template <class T>
119inline
120typename CachedPointer<T>::pointer_t
121CachedPointer<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 */
130template <class T>
131inline
132const typename CachedPointer<T>::pointer_t*
133CachedPointer<T>::ptr() const
134{
135 return &m_e;
136}
137
138} // namespace CxxUtils