carl  24.04
Computer ARithmetic Library
LocalPool.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include "../config.h"
4 #include "IDPool.h"
5 #include "PoolHelper.h"
6 
7 #include <boost/intrusive/unordered_set.hpp>
8 #include <memory>
9 
10 namespace carl::pool {
11 
12  template<class Content>
13  class LocalPool;
14 
15  template<class Content>
16  class LocalPoolElementWrapper : public boost::intrusive::unordered_set_base_hook<> {
18 
19  std::size_t m_id;
20  std::weak_ptr<LocalPoolElementWrapper<Content>> m_weak_ptr;
21  std::shared_ptr<LocalPool<Content>> m_pool;
22  Content m_content;
23 
24  public:
25  template <typename ...Args>
26  explicit LocalPoolElementWrapper(std::shared_ptr<LocalPool<Content>> pool, Args && ...args) : m_pool(pool), m_content(std::forward<Args>(args)...) {}
28  m_pool->free(this);
29  }
30 
31  const Content& content() const {
32  return m_content;
33  }
34 
35  auto id() const {
36  return m_id;
37  }
38  };
39 
40  template<class Content>
41  inline std::size_t hash_value(const LocalPoolElementWrapper<Content>& wrapper) {
42  return wrapper.content().key().hash();
43  }
44 
45  template<class Content>
47  return c1.content().key() == c2.content().key();
48  }
49 
50  template<class Content>
51  class LocalPool {
53 
54  template<typename Key>
55  struct content_equal {
56  bool operator()(const Key& data, const LocalPoolElementWrapper<Content>& content) const {
57  return data == content.content().key();
58  }
59 
60  bool operator()(const LocalPoolElementWrapper<Content>& content, const Key& data) const {
61  return (*this)(data, content);
62  }
63  };
64 
65  template<typename Key>
66  struct content_hash {
67  std::size_t operator()(const Key& data) const {
68  return data.hash();
69  }
70  };
71 
72 
73  /// id allocator
75  //size_t mIdAllocator;
77  using UnderlyingSet = boost::intrusive::unordered_set<LocalPoolElementWrapper<Content>>;
78  std::unique_ptr<typename UnderlyingSet::bucket_type[]> m_pool_buckets;
79  /// The pool.
81 
82  #ifdef THREAD_SAFE
83  /// Mutex to avoid multiple access to the pool
84  mutable std::recursive_mutex m_mutex;
85  #define DATASTRUCTURES_POOL_LOCK_GUARD std::lock_guard<std::recursive_mutex> lock(m_mutex);
86  #define DATASTRUCTURES_POOL_LOCK m_mutex.lock();
87  #define DATASTRUCTURES_POOL_UNLOCK m_mutex.unlock();
88  #else
89  #define DATASTRUCTURES_POOL_LOCK_GUARD
90  #define DATASTRUCTURES_POOL_LOCK
91  #define DATASTRUCTURES_POOL_UNLOCK
92  #endif
93 
94  void check_rehash() {
95  auto rehash = m_rehash_policy.needRehash(m_pool.bucket_count(), m_pool.size());
96  if (rehash.first) {
97  auto new_buckets = new typename UnderlyingSet::bucket_type[rehash.second];
98  m_pool.rehash(typename UnderlyingSet::bucket_traits(new_buckets, rehash.second));
99  m_pool_buckets.reset(new_buckets);
100  }
101  }
102 
103  public:
104  LocalPool(std::size_t _capacity = 1000)
105  : m_pool_buckets(new typename UnderlyingSet::bucket_type[m_rehash_policy.numBucketsFor(_capacity)]),
106  m_pool(typename UnderlyingSet::bucket_traits(m_pool_buckets.get(), m_rehash_policy.numBucketsFor(_capacity))) {
107  m_ids.get();
108  assert(m_ids.largestID() == 0);
109  }
110 
112 
113  template<typename Key>
114  std::shared_ptr<LocalPoolElementWrapper<Content>> add(std::shared_ptr<LocalPool<Content>> pool, Key&& c) {
116  assert(pool.get() == this);
117 
118  typename UnderlyingSet::insert_commit_data insert_data;
119  auto res = m_pool.insert_check(c, content_hash<Key>(), content_equal<Key>(), insert_data);
120  if (!res.second) {
121  return res.first->m_weak_ptr.lock();
122  } else {
123  auto shared = std::make_shared<LocalPoolElementWrapper<Content>>(pool, std::move(c));
124  shared.get()->m_id = m_ids.get();
125  shared.get()->m_weak_ptr = shared;
126  m_pool.insert_commit(*shared.get(), insert_data);
127  check_rehash();
128  return shared;
129  }
130  }
131 
132  protected:
133 
135  if (c->id() != 0) {
137  auto it = m_pool.find(*c);
138  assert(it != m_pool.end());
139  m_pool.erase(it);
140  m_ids.free(c->id());
141  }
142  }
143  };
144 
145  template<class Content>
147  std::shared_ptr<LocalPoolElementWrapper<Content>> m_content;
148 
149  public:
150  template<typename Key>
151  LocalPoolElement(std::shared_ptr<LocalPool<Content>>& pool, Key&& k) : m_content(pool->add(pool, std::move(k))) {}
152 
153  const Content& operator()() const {
154  return m_content->content();
155  }
156  const Content& operator*() const {
157  return m_content->content();
158  }
159  const Content* operator->() const {
160  return &(m_content->content());
161  }
162 
163  auto id() const {
164  return m_content->id();
165  }
166 
167  bool operator==(const LocalPoolElement& other) const {
168  return m_content == other.m_content;
169  }
170  };
171 
172 
173 }
#define DATASTRUCTURES_POOL_LOCK_GUARD
Definition: LocalPool.h:89
Coeff content(const UnivariatePolynomial< Coeff > &p)
The content of a polynomial is the gcd of the coefficients of the normal part of a polynomial.
Definition: Content.h:22
std::size_t hash_value(const LocalPoolElementWrapper< Content > &wrapper)
Definition: LocalPool.h:41
bool operator==(const LocalPoolElementWrapper< Content > &c1, const LocalPoolElementWrapper< Content > &c2)
Definition: LocalPool.h:46
auto & get(const std::string &name)
std::size_t get()
Definition: IDPool.h:30
std::size_t largestID() const
Definition: IDPool.h:26
void free(std::size_t id)
Definition: IDPool.h:41
pool::RehashPolicy m_rehash_policy
Definition: LocalPool.h:76
std::shared_ptr< LocalPoolElementWrapper< Content > > add(std::shared_ptr< LocalPool< Content >> pool, Key &&c)
Definition: LocalPool.h:114
IDPool m_ids
id allocator
Definition: LocalPool.h:74
std::unique_ptr< typename UnderlyingSet::bucket_type[]> m_pool_buckets
Definition: LocalPool.h:78
UnderlyingSet m_pool
The pool.
Definition: LocalPool.h:80
void free(const LocalPoolElementWrapper< Content > *c)
Definition: LocalPool.h:134
LocalPool(std::size_t _capacity=1000)
Definition: LocalPool.h:104
boost::intrusive::unordered_set< LocalPoolElementWrapper< Content > > UnderlyingSet
Definition: LocalPool.h:77
std::shared_ptr< LocalPool< Content > > m_pool
Definition: LocalPool.h:21
std::weak_ptr< LocalPoolElementWrapper< Content > > m_weak_ptr
Definition: LocalPool.h:20
LocalPoolElementWrapper(std::shared_ptr< LocalPool< Content >> pool, Args &&...args)
Definition: LocalPool.h:26
const Content & content() const
Definition: LocalPool.h:31
bool operator()(const Key &data, const LocalPoolElementWrapper< Content > &content) const
Definition: LocalPool.h:56
bool operator()(const LocalPoolElementWrapper< Content > &content, const Key &data) const
Definition: LocalPool.h:60
std::size_t operator()(const Key &data) const
Definition: LocalPool.h:67
LocalPoolElement(std::shared_ptr< LocalPool< Content >> &pool, Key &&k)
Definition: LocalPool.h:151
std::shared_ptr< LocalPoolElementWrapper< Content > > m_content
Definition: LocalPool.h:147
const Content * operator->() const
Definition: LocalPool.h:159
bool operator==(const LocalPoolElement &other) const
Definition: LocalPool.h:167
const Content & operator*() const
Definition: LocalPool.h:156
const Content & operator()() const
Definition: LocalPool.h:153
Mimics stdlibs default rehash policy for hashtables.
Definition: PoolHelper.h:15
std::pair< bool, std::size_t > needRehash(std::size_t numBuckets, std::size_t numElements) const
Definition: PoolHelper.cpp:14