mCRL2
Loading...
Searching...
No Matches
shared_reference.h
Go to the documentation of this file.
1// Author(s): Maurice Laveaux
2// Copyright: see the accompanying file COPYING or copy at
3// https://github.com/mCRL2org/mCRL2/blob/master/COPYING
4//
5// Distributed under the Boost Software License, Version 1.0.
6// (See accompanying file LICENSE_1_0.txt or copy at
7// http://www.boost.org/LICENSE_1_0.txt)
8//
9
10#ifndef MCRL2_UTILITIES_SHARED_REFERENCE_H_
11#define MCRL2_UTILITIES_SHARED_REFERENCE_H_
12
13#include "tagged_pointer.h"
14
15#include <cassert>
16#include <atomic>
17#include <type_traits>
18
20
21namespace mcrl2
22{
23namespace utilities
24{
25
27constexpr static bool EnableReferenceCountMetrics = false;
28
32template<typename T, bool ThreadSafe = false>
34{
35public:
38 {}
39
41 std::size_t reference_count() const
42 {
43 return m_reference_count;
44 }
45
48 {
49 if constexpr (ThreadSafe)
50 {
51 m_reference_count.fetch_add(1, std::memory_order_relaxed);
52 }
53 else
54 {
56 }
58 }
59
62 {
63 if constexpr (ThreadSafe)
64 {
65 m_reference_count.fetch_sub(1, std::memory_order_release);
66 }
67 else
68 {
70 }
72 }
73
75 static std::atomic<std::size_t>& reference_count_changes()
76 {
77 static std::atomic<std::size_t> g_reference_count_changes;
78 return g_reference_count_changes;
79 }
80
83 {
84 if constexpr (EnableReferenceCountMetrics)
85 {
87 }
88 }
89
90protected:
91 using SizeType = typename std::conditional<ThreadSafe, std::atomic<std::size_t>, std::size_t>::type;
92
93 // The underlying reference counter can always be changed.
95};
96
101template<typename T>
103{
104public:
105
108 : m_reference(nullptr)
109 {}
110
113 shared_reference(T* reference) noexcept
114 : m_reference(reference)
115 {
116 assert(defined());
117 m_reference->increment_reference_count();
118 }
119
122 : m_reference(other.m_reference)
123 {
124 if (defined())
125 {
126 m_reference->increment_reference_count();
127 }
128 }
129
132 : m_reference(other.m_reference)
133 {
134 other.m_reference = nullptr;
135 }
136
138 {
139 if (defined())
140 {
141 m_reference->decrement_reference_count();
142 }
143 }
144
147 {
148 // Increment first to prevent the same reference from getting a reference count of zero temporarily.
149 if (other.defined())
150 {
151 other.m_reference->increment_reference_count();
152 }
153
154 // Decrement the reference from the reference that is currently referred to.
155 if (defined())
156 {
157 m_reference->decrement_reference_count();
158 }
159
160 m_reference=other.m_reference;
161 return *this;
162 }
163
166 {
167 if (defined())
168 {
169 m_reference->decrement_reference_count();
170 }
171
172 m_reference = other.m_reference;
173 other.m_reference = nullptr;
174 return *this;
175 }
176
178 bool defined() const
179 {
180 return m_reference.get() != nullptr;
181 }
182
183 bool operator ==(const shared_reference<T>& other) const noexcept
184 {
185 return m_reference == other.m_reference;
186 }
187
188 bool operator <(const shared_reference<T>& other) const noexcept
189 {
190 return m_reference < other.m_reference;
191 }
192
193 // Comparison operators follow from equivalence and less than.
194 bool operator !=(const shared_reference<T>& other) const noexcept
195 {
196 return m_reference != other.m_reference;
197 }
198
199 bool operator <=(const shared_reference<T>& other) const noexcept
200 {
201 return m_reference <= other.m_reference;
202 }
203
204 bool operator >(const shared_reference<T>& other) const noexcept
205 {
206 return m_reference > other.m_reference;
207 }
208
209 bool operator >=(const shared_reference& other) const noexcept
210 {
211 return m_reference >= other.m_reference;
212 }
213
214 T* operator->() const noexcept
215 {
216 assert(defined());
217 return m_reference.get();
218 }
219
220 T* get() const noexcept
221 {
222 assert(defined());
223 return m_reference.get();
224 }
225
226 T& operator*() const noexcept
227 {
228 assert(defined());
229 return *m_reference;
230 }
231
234 {
235 m_reference.swap(other.m_reference);
236 }
237
238 bool tagged() const noexcept
239 {
240 return m_reference.tagged();
241 }
242
243 void tag() const
244 {
245 m_reference.tag();
246 }
247
248 void untag() const
249 {
250 m_reference.untag();
251 }
252
253private:
255};
256
257} // namespace utilities
258} // namespace mcrl2
259
260namespace std
261{
262
263template<typename T>
265{
266 a.swap(b);
267}
268
269} // namespace std
270
271#endif // MCRL2_UTILITIES_SHARED_REFERENCE_H_
Stores a reference count that can be incremented and decremented.
static void count_reference_count_changes()
Increment the number of reference count changes.
typename std::conditional< ThreadSafe, std::atomic< std::size_t >, std::size_t >::type SizeType
std::size_t reference_count() const
Obtain the reference count.
void increment_reference_count() const
Increment the reference count by one.
static std::atomic< std::size_t > & reference_count_changes()
Obtain the number of times that this reference count has changed.
void decrement_reference_count() const
Decrement the reference count by one.
A reference counted reference to a shared_reference_counted object.
bool operator==(const shared_reference< T > &other) const noexcept
bool operator>=(const shared_reference &other) const noexcept
shared_reference< T > & operator=(shared_reference< T > &&other) noexcept
Move assignment constructor.
bool defined() const
Check whether the shared_reference has a valid reference.
bool operator>(const shared_reference< T > &other) const noexcept
shared_reference() noexcept
The default constructor.
void swap(shared_reference< T > &other)
Swaps *this with the other shared reference.
utilities::tagged_pointer< T > m_reference
shared_reference< T > & operator=(const shared_reference< T > &other) noexcept
Copy assignment constructor.
bool operator!=(const shared_reference< T > &other) const noexcept
bool operator<=(const shared_reference< T > &other) const noexcept
shared_reference(shared_reference< T > &&other) noexcept
Move constructor.
shared_reference(const shared_reference< T > &other) noexcept
Copy constructor.
bool operator<(const shared_reference< T > &other) const noexcept
shared_reference(T *reference) noexcept
Takes ownership of the passed reference, which means that its reference count is incremented.
A pointer storage object that uses a least significant bit as a mark. Can be used by objects that are...
static constexpr bool EnableReferenceCountMetrics
Enable to count the number of reference count changes.
A class that takes a linear process specification and checks all tau-summands of that LPS for conflue...
Definition indexed_set.h:72
STL namespace.
void swap(atermpp::unprotected_aterm_core &t1, atermpp::unprotected_aterm_core &t2) noexcept
Swaps two aterms.
Definition aterm.h:462