9#ifndef MCRL2_UTILITIES_DETAIL_BUCKETLIST_H_
10#define MCRL2_UTILITIES_DETAIL_BUCKETLIST_H_
31template<
typename Allocator,
typename ...Args>
32inline auto allocate(Allocator& allocator,
const Args&... args) ->
decltype(allocator.allocate_args(args...))
34 return allocator.allocate_args(args...);
37template<
typename Allocator,
typename ...Args>
38inline auto allocate(Allocator& allocator,
const Args&...) ->
decltype(allocator.allocate(1))
40 return allocator.allocate(1);
46template<
typename Key,
typename Allocator>
59 m_next.store(other.m_next.load());
60 other.m_next =
nullptr;
67 bool has_next() const noexcept {
return m_next.load(std::memory_order_relaxed) !=
nullptr; }
77 std::atomic<node_base*>
m_next =
nullptr;
86 template<
typename ...Args>
87 explicit node(Args&&... args)
93 const Key&
key() const noexcept {
return m_key; }
96 operator Key&() {
return m_key; }
103 template<
bool Constant = true>
109 using value_type =
typename std::conditional<Constant, const Key, Key>::type;
110 using reference =
typename std::conditional<Constant, const Key&, Key&>::type;
111 using pointer =
typename std::conditional<Constant, const Key*, Key*>::type;
142 return !(*
this != it);
184 using NodeAllocator =
typename std::allocator_traits<Allocator>::template rebind_alloc<Bucket::node>;
220 template<
typename ...Args>
224 node* new_node =
allocate(allocator, std::forward<Args>(args)...);
225 std::allocator_traits<NodeAllocator>::construct(allocator, new_node, std::forward<Args>(args)...);
237 template<
typename ...Args,
242 node* new_node =
allocate(allocator, std::forward<Args>(args)...);
243 std::allocator_traits<NodeAllocator>::construct(allocator, new_node, std::forward<Args>(args)...);
256 for (
auto it =
iterator(old_head); it != old_end; ++it)
258 if (equals(*it, std::forward<Args>(args)...))
261 std::allocator_traits<NodeAllocator>::destroy(allocator, new_node);
262 std::allocator_traits<NodeAllocator>::deallocate(allocator, new_node, 1);
263 return std::make_pair(it,
false);
272 return std::make_pair(
iterator(new_node),
true);
279 assert(current_node->
next() !=
nullptr);
282 node* erased_node =
reinterpret_cast<node*
>(current_node->
next());
289 std::allocator_traits<NodeAllocator>::destroy(allocator, erased_node);
290 std::allocator_traits<NodeAllocator>::deallocate(allocator, erased_node, 1);
301 node* current_node =
const_cast<node*
>(pos.get_node());
309 node* after_pos_node =
const_cast<node*
>(pos.get_node());
310 if (after_pos_node !=
nullptr)
321 last->set_next(after_pos_node);
336 node* current_node =
const_cast<node*
>(pos.get_node());
365 element = element->
next();
Iterator over all keys in a bucket list.
bool operator!=(const key_iterator &it) const noexcept
key_iterator()
Default constructor.
reference operator*() const
std::ptrdiff_t difference_type
node * get_node() noexcept
typename std::conditional< Constant, const Key *, Key * >::type pointer
bool operator==(const key_iterator &it) const noexcept
const node * get_node() const noexcept
std::forward_iterator_tag iterator_category
key_iterator & operator++()
key_iterator(node_base *current)
pointer operator->() const
typename std::conditional< Constant, const Key, Key >::type value_type
typename std::conditional< Constant, const Key &, Key & >::type reference
The nodes of the bucket list without carrying any additional informations. Used to make no different ...
bool has_next() const noexcept
std::atomic< node_base * > m_next
Pointer to the next node.
void set_next(node_base *next) noexcept
Set the next pointer to the given next pointer.
bool exchange(node_base *&expected, node_base *value)
node_base(node_base &&other) noexcept
node_base * next() const noexcept
The nodes of the bucket list.
node(Args &&... args)
Constructs a key by using the given arguments.
const Key & key() const noexcept
Key m_key
Store the actual key.
This essentially implements the std::forward_list, with the difference that it does not own the nodes...
void splice_after(const_iterator pos, bucket_list &other)
Moves the elements from other into this bucket after the given position.
key_iterator< false > iterator
key_iterator< true > const_iterator
const Key & front() const
bool contains(node *node)
iterator erase_after(NodeAllocator &allocator, const_iterator it)
Removes the element after the given iterator from the list. The returned iterator.
void clear(NodeAllocator &allocator)
Empties the bucket list.
const_iterator cend() const
const_iterator begin() const
const_iterator before_begin() const
const_iterator end() const
std::pair< iterator, bool > emplace_front_unique(NodeAllocator &allocator, const Equals &equals, Args &&...args)
Constructs an element using the allocator with the given arguments and insert it in the front of the ...
void splice_front(const_iterator pos, bucket_list &other)
Moves the first node from the given bucket into this bucket after the given position.
typename std::allocator_traits< Allocator >::template rebind_alloc< Bucket::node > NodeAllocator
Rebind the passed to allocator to a bucket list node allocator.
node_base m_head
The first node in the bucket list.
void emplace_front(NodeAllocator &allocator, Args &&...args)
Constructs an element using the allocator with the given arguments and insert it in the front.
const_iterator cbegin() const
static constexpr Sentinel EndIterator
A end of the iterator sentinel.
auto allocate(Allocator &allocator, const Args &... args) -> decltype(allocator.allocate_args(args...))
A compile time check for allocate_args in the given allocator, calls allocate(1) otherwise.
A class that takes a linear process specification and checks all tau-summands of that LPS for conflue...