carl  24.04
Computer ARithmetic Library
Pool.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 #include "Singleton.h"
7 
8 #include <boost/intrusive/unordered_set.hpp>
9 #include <memory>
10 
11 namespace carl::pool {
12 
13  template<class Content>
14  class Pool;
15 
16  template<class Content>
17  class PoolElementWrapper : public boost::intrusive::unordered_set_base_hook<> {
18  friend Pool<Content>;
19 
20  std::size_t m_id;
21  std::weak_ptr<PoolElementWrapper<Content>> m_weak_ptr;
22  Content m_content;
23 
24  public:
25  template <typename ...Args>
26  explicit PoolElementWrapper(Args && ...args) : m_content(std::forward<Args>(args)...) {}
28  Pool<Content>::getInstance().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 PoolElementWrapper<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 Pool : public Singleton<Pool<Content>> {
54 
55  template<typename Key>
56  struct content_equal {
57  bool operator()(const Key& data, const PoolElementWrapper<Content>& content) const {
58  return data == content.content().key();
59  }
60 
61  bool operator()(const PoolElementWrapper<Content>& content, const Key& data) const {
62  return (*this)(data, content);
63  }
64  };
65 
66  template<typename Key>
67  struct content_hash {
68  std::size_t operator()(const Key& data) const {
69  return data.hash();
70  }
71  };
72 
73 
74  /// id allocator
76  //size_t mIdAllocator;
78  using UnderlyingSet = boost::intrusive::unordered_set<PoolElementWrapper<Content>>;
79  std::unique_ptr<typename UnderlyingSet::bucket_type[]> m_pool_buckets;
80  /// The pool.
82 
83  #ifdef THREAD_SAFE
84  /// Mutex to avoid multiple access to the pool
85  mutable std::recursive_mutex m_mutex;
86  #define DATASTRUCTURES_POOL_LOCK_GUARD std::lock_guard<std::recursive_mutex> lock(m_mutex);
87  #define DATASTRUCTURES_POOL_LOCK m_mutex.lock();
88  #define DATASTRUCTURES_POOL_UNLOCK m_mutex.unlock();
89  #else
90  #define DATASTRUCTURES_POOL_LOCK_GUARD
91  #define DATASTRUCTURES_POOL_LOCK
92  #define DATASTRUCTURES_POOL_UNLOCK
93  #endif
94 
95  void check_rehash() {
96  auto rehash = m_rehash_policy.needRehash(m_pool.bucket_count(), m_pool.size());
97  if (rehash.first) {
98  auto new_buckets = new typename UnderlyingSet::bucket_type[rehash.second];
99  m_pool.rehash(typename UnderlyingSet::bucket_traits(new_buckets, rehash.second));
100  m_pool_buckets.reset(new_buckets);
101  }
102  }
103 
104  protected:
105 
106  explicit Pool(std::size_t _capacity = 1000)
107  : m_pool_buckets(new typename UnderlyingSet::bucket_type[m_rehash_policy.numBucketsFor(_capacity)]),
108  m_pool(typename UnderlyingSet::bucket_traits(m_pool_buckets.get(), m_rehash_policy.numBucketsFor(_capacity))) {
109  m_ids.get();
110  assert(m_ids.largestID() == 0);
111  }
112 
113  public:
114 
115  ~Pool() {}
116 
117  template<typename Key>
118  std::shared_ptr<PoolElementWrapper<Content>> add(Key&& c) {
120 
121  typename UnderlyingSet::insert_commit_data insert_data;
122  auto res = m_pool.insert_check(c, content_hash<Key>(), content_equal<Key>(), insert_data);
123  if (!res.second) {
124  return res.first->m_weak_ptr.lock();
125  } else {
126  auto shared = std::make_shared<PoolElementWrapper<Content>>(std::move(c));
127  shared.get()->m_id = m_ids.get();
128  shared.get()->m_weak_ptr = shared;
129  m_pool.insert_commit(*shared.get(), insert_data);
130  check_rehash();
131  return shared;
132  }
133  }
134 
135  protected:
136 
138  if (c->id() != 0) {
140  auto it = m_pool.find(*c);
141  assert(it != m_pool.end());
142  m_pool.erase(it);
143  m_ids.free(c->id());
144  }
145  }
146  };
147 
148  template<class Content>
149  class PoolElement {
150  std::shared_ptr<PoolElementWrapper<Content>> m_content;
151 
152  public:
153  template<typename Key>
154  PoolElement(Key&& k) : m_content(Pool<Content>::getInstance().add(std::move(k))) {}
155 
156  const Content& operator()() const {
157  return m_content->content();
158  }
159  const Content& operator*() const {
160  return m_content->content();
161  }
162  const Content* operator->() const {
163  return &(m_content->content());
164  }
165 
166  auto id() const {
167  return m_content->id();
168  }
169  };
170 
171 
172 }
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
std::unique_ptr< typename UnderlyingSet::bucket_type[]> m_pool_buckets
Definition: Pool.h:79
void check_rehash()
Definition: Pool.h:95
IDPool m_ids
id allocator
Definition: Pool.h:75
pool::RehashPolicy m_rehash_policy
Definition: Pool.h:77
std::shared_ptr< PoolElementWrapper< Content > > add(Key &&c)
Definition: Pool.h:118
Pool(std::size_t _capacity=1000)
Definition: Pool.h:106
boost::intrusive::unordered_set< PoolElementWrapper< Content > > UnderlyingSet
Definition: Pool.h:78
UnderlyingSet m_pool
The pool.
Definition: Pool.h:81
void free(const PoolElementWrapper< Content > *c)
Definition: Pool.h:137
const Content & content() const
Definition: Pool.h:31
PoolElementWrapper(Args &&...args)
Definition: Pool.h:26
std::weak_ptr< PoolElementWrapper< Content > > m_weak_ptr
Definition: Pool.h:21
bool operator()(const Key &data, const PoolElementWrapper< Content > &content) const
Definition: Pool.h:57
bool operator()(const PoolElementWrapper< Content > &content, const Key &data) const
Definition: Pool.h:61
std::size_t operator()(const Key &data) const
Definition: Pool.h:68
auto id() const
Definition: Pool.h:166
const Content & operator*() const
Definition: Pool.h:159
std::shared_ptr< PoolElementWrapper< Content > > m_content
Definition: Pool.h:150
PoolElement(Key &&k)
Definition: Pool.h:154
const Content * operator->() const
Definition: Pool.h:162
const Content & operator()() const
Definition: Pool.h:156
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
Base class that implements a singleton.
Definition: Singleton.h:24
static Pool< Content > & getInstance()
Returns the single instance of this class by reference.
Definition: Singleton.h:45
#define DATASTRUCTURES_POOL_LOCK_GUARD
Definition: Pool.h:90