Line data Source code
1 : // Author(s): Jan Friso Groote, 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 : /// \file mcrl2/data/standard_containers/vector.h
11 : /// \brief This file contains a vector class that behaves
12 : /// exactly as a standard vector. It can only be used
13 : /// to store class instances that derive from aterms.
14 : /// The stored aterms are protected as a whole, i.e.,
15 : /// time and memory is saved as individual protection
16 : /// per element is unnecessary.
17 :
18 : #ifndef MCRL2_ATERMPP_STANDARD_CONTAINER_VECTOR_H
19 : #define MCRL2_ATERMPP_STANDARD_CONTAINER_VECTOR_H
20 :
21 : #include <vector>
22 :
23 : #include "mcrl2/atermpp/detail/aterm_container.h"
24 : #include "mcrl2/atermpp/detail/thread_aterm_pool.h"
25 : #include "mcrl2/utilities/shared_mutex.h"
26 :
27 : /// \brief The main namespace for the aterm++ library.
28 : namespace atermpp
29 : {
30 :
31 : /// \brief A vector class in which aterms can be stored.
32 : template < class T, class Alloc = std::allocator<detail::reference_aterm<T> >, bool ThreadSafe = false >
33 : class vector : public std::vector< detail::reference_aterm<T>, Alloc >
34 : {
35 : protected:
36 : typedef std::vector< detail::reference_aterm<T>, Alloc > super;
37 :
38 : detail::generic_aterm_container<std::vector<detail::reference_aterm<T>, Alloc>> container_wrapper;
39 :
40 : public:
41 : /// Standard typedefs.
42 : typedef typename super::allocator_type allocator_type;
43 : typedef typename super::value_type value_type;
44 : typedef typename super::size_type size_type;
45 : typedef typename super::reference reference;
46 : typedef typename super::iterator iterator;
47 : typedef typename super::const_iterator const_iterator;
48 :
49 : /// \brief Default constructor.
50 15613 : vector()
51 : : super(),
52 15613 : container_wrapper(*this)
53 15613 : {}
54 :
55 : /// \brief Constructor.
56 : explicit vector (const allocator_type& alloc)
57 : : super::vector(alloc),
58 : container_wrapper(*this)
59 : {}
60 :
61 : /// \brief Constructor.
62 : explicit vector (size_type n, const allocator_type& alloc = allocator_type())
63 : : super::vector(n, alloc),
64 : container_wrapper(*this)
65 : {}
66 :
67 : vector (size_type n, const value_type& val, const allocator_type& alloc = allocator_type())
68 : : super::vector(n, detail::reference_aterm(val), alloc),
69 : container_wrapper(*this)
70 : {}
71 :
72 : /// \brief Constructor.
73 : template <class InputIterator>
74 : vector (InputIterator first, InputIterator last, const allocator_type& alloc = allocator_type())
75 : : super::vector(first, last, alloc),
76 : container_wrapper(*this)
77 : {}
78 :
79 : /// \brief Constructor.
80 8 : vector (const vector& x)
81 : : super::vector(x),
82 8 : container_wrapper(*this)
83 8 : {}
84 :
85 : /// \brief Constructor.
86 : vector (const vector& x, const allocator_type& alloc)
87 : : super::vector(x, alloc),
88 : container_wrapper(*this)
89 : {}
90 :
91 : /// \brief Constructor.
92 4 : vector (vector&& x)
93 4 : : super::vector(std::move(x)),
94 4 : container_wrapper(*this)
95 4 : {}
96 :
97 : /// \brief Constructor.
98 : vector (vector&& x, const allocator_type& alloc)
99 : : super::vector(std::move(x), alloc),
100 : container_wrapper(*this)
101 : {}
102 :
103 : /// \brief Constructor. To be done later....
104 : vector (std::initializer_list<value_type> il, const allocator_type& alloc = allocator_type())
105 : : super::vector(il, alloc),
106 : container_wrapper(*this)
107 : {}
108 :
109 : /// \brief Assignment operator.
110 : vector& operator=(const vector& x) = default;
111 :
112 : /// \brief Move assignment operator
113 : vector& operator=(vector&& x) = default;
114 :
115 : /// \brief Standard destructor.
116 15625 : ~vector() {}
117 :
118 : void shrink_to_fit()
119 : {
120 : if constexpr (ThreadSafe) {
121 : mcrl2::utilities::lock_guard guard = detail::g_thread_term_pool().lock();
122 : super::shrink_to_fit();
123 : } else {
124 : mcrl2::utilities::shared_guard guard = detail::g_thread_term_pool().lock_shared();
125 : super::shrink_to_fit();
126 : }
127 : }
128 :
129 : void clear() noexcept
130 : {
131 : if constexpr (ThreadSafe) {
132 : mcrl2::utilities::lock_guard guard = detail::g_thread_term_pool().lock();
133 : super::clear();
134 : } else {
135 : mcrl2::utilities::shared_guard guard = detail::g_thread_term_pool().lock_shared();
136 : super::clear();
137 : }
138 : }
139 :
140 : iterator insert( const_iterator pos, const T& value )
141 : {
142 : if constexpr (ThreadSafe) {
143 : mcrl2::utilities::lock_guard guard = detail::g_thread_term_pool().lock();
144 :
145 : // This is not thread safe otherwise since the length or end iterator is updated during this producedure.
146 : return super::insert(pos, value);
147 : }
148 :
149 : mcrl2::utilities::shared_guard guard = detail::g_thread_term_pool().lock_shared();
150 : return super::insert(pos, value);
151 : }
152 :
153 : iterator insert( const_iterator pos, T&& value )
154 : {
155 : if constexpr (ThreadSafe) {
156 : mcrl2::utilities::lock_guard guard = detail::g_thread_term_pool().lock();
157 : return super::insert(pos, value);
158 : }
159 :
160 : mcrl2::utilities::shared_guard guard = detail::g_thread_term_pool().lock_shared();
161 : return super::insert(pos, value);
162 : }
163 :
164 : iterator insert( const_iterator pos, size_type count, const T& value )
165 : {
166 : if constexpr (ThreadSafe) {
167 : mcrl2::utilities::lock_guard guard = detail::g_thread_term_pool().lock();
168 : return super::insert(pos, count, value);
169 : }
170 :
171 : mcrl2::utilities::shared_guard guard = detail::g_thread_term_pool().lock_shared();
172 : return super::insert(pos, count, value);
173 : }
174 :
175 : template< class InputIt >
176 : iterator insert( const_iterator pos,
177 : InputIt first, InputIt last )
178 : {
179 : if constexpr (ThreadSafe) {
180 : mcrl2::utilities::lock_guard guard = detail::g_thread_term_pool().lock();
181 : return super::insert(pos, first, last);
182 : }
183 :
184 : mcrl2::utilities::shared_guard guard = detail::g_thread_term_pool().lock_shared();
185 : return super::insert(pos, first, last);
186 : }
187 :
188 : iterator insert( const_iterator pos, std::initializer_list<T> ilist )
189 : {
190 : if constexpr (ThreadSafe) {
191 : mcrl2::utilities::lock_guard guard = detail::g_thread_term_pool().lock();
192 : return super::insert(pos, ilist);
193 : }
194 :
195 : mcrl2::utilities::shared_guard guard = detail::g_thread_term_pool().lock_shared();
196 : return super::insert(pos, ilist);
197 : }
198 :
199 : template< class... Args >
200 : iterator emplace( const_iterator pos, Args&&... args )
201 : {
202 : if constexpr (ThreadSafe) {
203 : mcrl2::utilities::lock_guard guard = detail::g_thread_term_pool().lock();
204 : return super::emplace(pos, args...);
205 : }
206 :
207 : mcrl2::utilities::shared_guard guard = detail::g_thread_term_pool().lock_shared();
208 : return super::emplace(pos, args...);
209 : }
210 :
211 : iterator erase( const_iterator pos )
212 : {
213 : if constexpr (ThreadSafe) {
214 : mcrl2::utilities::lock_guard guard = detail::g_thread_term_pool().lock();
215 : return super::erase(pos);
216 : }
217 :
218 : mcrl2::utilities::shared_guard guard = detail::g_thread_term_pool().lock_shared();
219 : return super::erase(pos);
220 : }
221 :
222 : iterator erase( const_iterator first, const_iterator last )
223 : {
224 : if constexpr (ThreadSafe) {
225 : mcrl2::utilities::lock_guard guard = detail::g_thread_term_pool().lock();
226 : return super::erase(first, last);
227 : }
228 :
229 : mcrl2::utilities::shared_guard guard = detail::g_thread_term_pool().lock_shared();
230 : return super::erase(first, last);
231 : }
232 :
233 100003681 : void push_back( const T& value )
234 : {
235 : if constexpr (ThreadSafe) {
236 : mcrl2::utilities::lock_guard guard = detail::g_thread_term_pool().lock();
237 : super::push_back(value);
238 : } else {
239 100003681 : mcrl2::utilities::shared_guard guard = detail::g_thread_term_pool().lock_shared();
240 100003681 : super::push_back(value);
241 100003681 : }
242 100003681 : }
243 :
244 1 : void push_back( T&& value )
245 : {
246 : if constexpr (ThreadSafe) {
247 : mcrl2::utilities::lock_guard guard = detail::g_thread_term_pool().lock();
248 : super::push_back(value);
249 : } else {
250 1 : mcrl2::utilities::shared_guard guard = detail::g_thread_term_pool().lock_shared();
251 1 : super::push_back(value);
252 1 : }
253 1 : }
254 :
255 : template< class... Args >
256 3892 : reference emplace_back( Args&&... args )
257 : {
258 : if constexpr (ThreadSafe) {
259 3892 : mcrl2::utilities::lock_guard guard = detail::g_thread_term_pool().lock();
260 3892 : return super::emplace_back(args...);
261 3892 : }
262 :
263 : mcrl2::utilities::shared_guard guard = detail::g_thread_term_pool().lock_shared();
264 : return super::emplace_back(args...);
265 : }
266 :
267 : void pop_back()
268 : {
269 : if constexpr (ThreadSafe) {
270 : mcrl2::utilities::lock_guard guard = detail::g_thread_term_pool().lock();
271 : super::pop_back();
272 : } else {
273 : mcrl2::utilities::shared_guard guard = detail::g_thread_term_pool().lock_shared();
274 : super::pop_back();
275 : }
276 : }
277 :
278 1807 : void resize( size_type count )
279 : {
280 : if constexpr (ThreadSafe) {
281 : mcrl2::utilities::lock_guard guard = detail::g_thread_term_pool().lock();
282 : super::resize(count);
283 : } else {
284 1807 : mcrl2::utilities::shared_guard guard = detail::g_thread_term_pool().lock_shared();
285 1807 : super::resize(count);
286 1807 : }
287 1807 : }
288 :
289 : void resize( size_type count, const value_type& value )
290 : {
291 : if constexpr (ThreadSafe) {
292 : mcrl2::utilities::lock_guard guard = detail::g_thread_term_pool().lock();
293 : super::resize(count, value);
294 : } else {
295 : mcrl2::utilities::shared_guard guard = detail::g_thread_term_pool().lock_shared();
296 : super::resize(count, value);
297 : }
298 : }
299 :
300 : void swap( vector& other ) noexcept
301 : {
302 : if constexpr (ThreadSafe) {
303 : mcrl2::utilities::lock_guard guard = detail::g_thread_term_pool().lock();
304 : super::swap(other); // Invalidates end() so must be protected.
305 : } else {
306 : mcrl2::utilities::shared_guard guard = detail::g_thread_term_pool().lock_shared();
307 : super::swap(other); // Invalidates end() so must be protected.
308 : }
309 : }
310 :
311 12109 : std::size_t size() const
312 : {
313 : // Concurrent read/write on the size.
314 12109 : mcrl2::utilities::shared_guard guard = detail::g_thread_term_pool().lock_shared();
315 24218 : return super::size();
316 12109 : }
317 : };
318 :
319 : } // namespace atermpp
320 : #endif // MCRL2_ATERMPP_STANDARD_CONTAINER_VECTOR_H
|