mCRL2
Loading...
Searching...
No Matches
aterm_container.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_ATERMPP_DETAIL_ATERM_CONTAINER_H
11#define MCRL2_ATERMPP_DETAIL_ATERM_CONTAINER_H
12
13#include <stack>
14#include <type_traits>
15#include "mcrl2/atermpp/aterm.h"
19
20namespace atermpp
21{
22
23typedef std::stack<std::reference_wrapper<detail::_aterm>> term_mark_stack;
24
25inline void mark_term(const aterm& t, term_mark_stack& todo)
26{
27 if (t.defined())
28 {
30 }
31}
32
33
34namespace detail
35{
36
43{
44public:
45 aterm_container(std::function<void(term_mark_stack&)> mark_func, std::function<std::size_t()> size_func);
47
49 void mark(term_mark_stack& todo) const
50 {
51 mark_func(todo);
52 }
53
54 inline std::size_t size() const
55 {
56 return size_func();
57 }
58
59private:
60 std::function<void(term_mark_stack&)> mark_func;
61 std::function<std::size_t()> size_func;
62};
63
64template<class T, typename Type = void >
65class reference_aterm;
66
67
68template<class T>
69struct is_pair_helper : public std::false_type
70{};
71
72template<class T, class U>
73struct is_pair_helper<std::pair<T,U> > : public std::true_type
74{};
75
76template<class T>
77struct is_pair : public is_pair_helper<typename std::decay<T>::type >
78{};
79
80template<class T>
81struct is_reference_aterm_helper : public std::false_type
82{};
83
84template<class T>
85struct is_reference_aterm_helper<reference_aterm<T> > : public std::true_type
86{};
87
88template<class T>
89struct is_reference_aterm : public is_reference_aterm_helper<typename std::decay<T>::type >
90{};
91
93template<class T, typename Type >
95{
96protected:
97 typedef typename std::decay<T>::type T_type;
99public:
100 reference_aterm() = default;
101
102 reference_aterm(const T_type& other) noexcept
103 : m_t(other)
104 { }
105
106 template <class... Args>
107 reference_aterm(Args&&... args) noexcept
108 : m_t(std::forward<Args>(args)...)
109 { }
110
111 template <class... Args>
112 reference_aterm(const Args&... args) noexcept
113 : m_t(args...)
114 { }
115
116 reference_aterm(T_type&& other) noexcept
117 : m_t(std::forward(other))
118 {}
119
120 const reference_aterm& operator=(const T_type& other) noexcept
121 {
122 static_assert(std::is_base_of<aterm, T_type>::value);
123 m_t=other;
124 return m_t;
125 }
126
127 const reference_aterm& operator=(T_type&& other) noexcept
128 {
129 static_assert(std::is_base_of<aterm, T_type>::value);
130 m_t = std::forward(other);
131 return m_t;
132 }
133
135 operator T_type&()
136 {
137 return m_t;
138 }
139
140 operator const T_type&() const
141 {
142 return m_t;
143 }
144
152 void mark(std::stack<std::reference_wrapper<detail::_aterm>>& todo) const
153 {
154 m_t.mark(todo);
155 }
156
157};
158
161template<class T>
162class reference_aterm < T, typename std::enable_if<std::is_fundamental<typename std::decay<T>::type>::value>::type >
163{
164protected:
165 typedef typename std::decay<T>::type T_type;
167
168public:
169
171 reference_aterm() noexcept = default;
172
173 reference_aterm(const T& other) noexcept
174 : m_t(other)
175 { }
176
177 reference_aterm(T_type&& other) noexcept
178 : m_t(std::move(other))
179 {}
180
181 const T& operator=(const T& other) noexcept
182 {
183 m_t=other;
184 return m_t;
185 }
186
187 const T& operator=(T&& other) noexcept
188 {
189 m_t = std::move(other);
190 return m_t;
191 }
192
194 operator T&()
195 {
196 return m_t;
197 }
198
199 operator const T&() const
200 {
201 return m_t;
202 }
203
204 void mark(std::stack<std::reference_wrapper<detail::_aterm>>& /* todo */) const
205 {
206 /* Do nothing */
207 }
208
209 bool operator==(const reference_aterm& other) const
210 {
211 return m_t==other.m_t;
212 }
213
214};
215
217template<typename T>
218class reference_aterm<T, typename std::enable_if<std::is_base_of<aterm, T>::value>::type> : public unprotected_aterm
219{
220public:
222 reference_aterm() noexcept = default;
223
224 explicit reference_aterm(const unprotected_aterm& other) noexcept
225 {
226 m_term = detail::address(other);
227 }
228
229 reference_aterm(const T& other) noexcept
231 { }
232
235 {
236 }
237
238 const reference_aterm& operator=(const unprotected_aterm& other) noexcept;
240
242 operator T&()
243 {
244 static_assert(std::is_base_of<aterm, T>::value,"Term must be derived from an aterm");
245 static_assert(sizeof(T)==sizeof(std::size_t),"Term derived from an aterm must not have extra fields");
246 return reinterpret_cast<T&>(*this);
247 }
248
249 operator const T&() const
250 {
251 static_assert(std::is_base_of<aterm, T>::value,"Term must be derived from an aterm");
252 static_assert(sizeof(T)==sizeof(std::size_t),"Term derived from an aterm must not have extra fields");
253 return reinterpret_cast<const T&>(*this);
254
255 }
256
257 void mark(std::stack<std::reference_wrapper<detail::_aterm>>& todo) const
258 {
259 if (defined())
260 {
261 mark_term(*m_term,todo);
262 }
263 }
264};
265
266template<typename T>
267typename std::pair<typename std::conditional<is_reference_aterm<typename T::first_type>::value,
268 typename T::first_type,
269 reference_aterm< typename T::first_type > >::type,
270 typename std::conditional<is_reference_aterm<typename T::second_type>::value,
271 typename T::second_type,
272 reference_aterm< typename T::second_type > >::type >
274{
276 {
277 return other;
278 }
280 {
281 return std::pair(other.first, reference_aterm<typename T::second_type>(other.second));
282 }
284 {
285 return std::pair(reference_aterm<typename T::first_type>(other.first),other.second);
286 }
287 else
288 {
291
292 return std::pair(reference_aterm<typename T::first_type>(other.first), reference_aterm<typename T::second_type>(other.second));
293 }
294}
295
296
297
298
301template<typename T>
302class reference_aterm<T, typename std::enable_if<is_pair<T>::value>::type > :
303 public std::pair<typename std::conditional<is_reference_aterm<typename T::first_type>::value,
304 typename T::first_type,
305 reference_aterm< typename T::first_type > >::type,
306 typename std::conditional<is_reference_aterm<typename T::second_type>::value,
307 typename T::second_type,
308 reference_aterm< typename T::second_type > >::type >
309{
310protected:
311 typedef std::pair<typename std::conditional<is_reference_aterm<typename T::first_type>::value,
312 typename T::first_type,
314 typename std::conditional<is_reference_aterm<typename T::second_type>::value,
315 typename T::second_type,
317 typedef T std_pair;
318
319public:
321 reference_aterm() = default;
322
324 : super()
325 {
326 *this = other;
327 }
328
331 {}
332
334 : super(reference_aterm<typename T::first_type >(std::move(other.first)),
335 reference_aterm<typename T::second_type>(std::move(other.second)))
336 {}
337
339 {
340 super::first=other.first;
341 super::second=other.second;
342 return *this;
343 }
344
345 const reference_aterm& operator=(const std_pair& other)
346 {
347 super::first=other.first;
348 super::second=other.second;
349 return *this;
350 }
351
353 {
354 super::first = std::move(other.first);
355 super::second = std::move(other.second);
356 return *this;
357 }
358
360 {
361 super::first = other.first;
362 super::second = other.second;
363 return *this;
364 }
365
366
368 operator std_pair&()
369 {
370 return reinterpret_cast<std_pair>(*this);
371 }
372
373 operator const std_pair&() const
374 {
375 return *reinterpret_cast<std_pair const*>(this);
376 }
377
378 void mark(std::stack<std::reference_wrapper<detail::_aterm>>& todo) const
379 {
381 {
382 super::first.mark(todo);
383 }
384 else
385 {
387 }
388
390 {
391 super::second.mark(todo);
392 }
393 else
394 {
396 }
397 }
398};
399
400template<typename T, typename Allocator>
402{
403public:
404 using value_type = T;
405 using size_type = std::size_t;
406 using difference_type = std::ptrdiff_t;
407
408 //static_assert(std::is_same_v<value_type, typename Allocator::value_type>, "Types should be equal");
409
410 template <class U>
411 struct rebind
412 {
414 };
415
416 aterm_allocator() = default;
417
420 T* allocate(size_type n, const void* hint = nullptr)
421 {
422 return m_allocator.allocate(n, hint);
423 }
424
427 void deallocate(T* p, size_type n);
428
429 // Move assignment and construction is possible.
432
433private:
434 Allocator m_allocator;
435};
436
437template<typename Container>
439{
440public:
442 generic_aterm_container(const Container& container)
443 : m_container(std::bind([&container](term_mark_stack& todo) {
444 // Marking contained terms.
445 for (const typename Container::value_type& element: container)
446 {
449 {
451 element.mark(todo);
452 }
453 else
454 {
457 }
458 }
459 }, std::placeholders::_1),
460 std::bind([&container]() -> std::size_t {
461 // Return the number of elements in the container.
462 return container.size();
463 }))
464 {}
465
466 // Container is a reference so unclear what to do in these cases.
469
470 // It is fine here if the container gets updated, but the functions stay the same.
472 {
473 return *this;
474 };
475
477 {
478 return *this;
479 }
480
481protected:
483};
484
485} // namespace detail
486} // namespace atermpp
487
488namespace std
489{
490
492template<class T>
493struct hash<atermpp::detail::reference_aterm<T>>
494{
496 {
497 return std::hash<T>()(t);
498 }
499};
500
501} // namespace std
502
503#endif // MCRL2_ATERMPP_DETAIL_ATERM_CONTAINER_H
The aterm base class that provides protection of the underlying shared terms.
Definition aterm.h:186
aterm_allocator(aterm_allocator &&)=default
T * allocate(size_type n, const void *hint=nullptr)
aterm_allocator & operator=(aterm_allocator &&)=default
Provides safe storage of unprotected_aterm instances in a container by marking them during garbage co...
std::function< std::size_t()> size_func
std::function< void(term_mark_stack &)> mark_func
void mark(term_mark_stack &todo) const
Ensure that all the terms in the containers.
generic_aterm_container & operator=(const generic_aterm_container &)
generic_aterm_container(const generic_aterm_container &)=delete
generic_aterm_container(generic_aterm_container &&)=delete
generic_aterm_container & operator=(generic_aterm_container &)
generic_aterm_container(const Container &container)
Constructor.
std::pair< typename std::conditional< is_reference_aterm< typename T::first_type >::value, typename T::first_type, reference_aterm< typename T::first_type > >::type, typename std::conditional< is_reference_aterm< typename T::second_type >::value, typename T::second_type, reference_aterm< typename T::second_type > >::type > super
void mark(std::stack< std::reference_wrapper< detail::_aterm > > &todo) const
Base class that should not be used.
reference_aterm(Args &&... args) noexcept
void mark(std::stack< std::reference_wrapper< detail::_aterm > > &todo) const
reference_aterm(const T_type &other) noexcept
const reference_aterm & operator=(T_type &&other) noexcept
reference_aterm(const Args &... args) noexcept
reference_aterm(T_type &&other) noexcept
const reference_aterm & operator=(const T_type &other) noexcept
An unprotected term does not change the reference count of the shared term when it is copied or moved...
Definition aterm.h:36
bool defined() const
Returns true if this term is not equal to the term assigned by the default constructor of aterms,...
Definition aterm.h:147
Inherit from this class to prevent it from being copyable.
Definition noncopyable.h:21
_aterm * address(const unprotected_aterm &t)
Definition aterm.h:347
std::pair< typename std::conditional< is_reference_aterm< typename T::first_type >::value, typename T::first_type, reference_aterm< typename T::first_type > >::type, typename std::conditional< is_reference_aterm< typename T::second_type >::value, typename T::second_type, reference_aterm< typename T::second_type > >::type > reference_aterm_pair_constructor_helper(const T &other)
void mark_term(const _aterm &root, std::stack< std::reference_wrapper< _aterm > > &todo)
Marks a term and recursively all arguments that are not reachable.
The main namespace for the aterm++ library.
Definition algorithm.h:21
std::stack< std::reference_wrapper< detail::_aterm > > term_mark_stack
void mark_term(const aterm &t, term_mark_stack &todo)
STL namespace.
aterm_allocator< U, typename Allocator::template rebind< U >::other > other
std::size_t operator()(const atermpp::detail::reference_aterm< T > &t) const
#define hash(l, r, m)
Definition tree_set.cpp:23