3#include <absl/container/flat_hash_set.h>
14inline static constexpr size_t SizeOf =
sizeof(std::conditional_t<std::is_pointer_v<T>, uintptr_t, T>);
16template<
class T>
class Pool;
22 constexpr Data() noexcept = default;
32 for (
size_t i = 0, e = d1->
size; res && i != e; ++i) res &= d1->
elems[i] == d2->
elems[i];
38 if (!d)
return H::combine(std::move(h), 0);
39 return H::combine_contiguous(std::move(h), d->elems, d->size);
43 static_assert(
sizeof(Data) ==
sizeof(size_t),
"Data.elems should be 0");
48 constexpr PooledSet(
const Data* data) noexcept
55 constexpr
void clear() noexcept { data_ =
nullptr; }
60 constexpr explicit operator bool() const noexcept {
return data_; }
61 constexpr bool empty() const noexcept {
return data_ ==
nullptr; }
62 constexpr size_t size() const noexcept {
return empty() ? 0 : data_->
size; }
64 constexpr const T&
front()
const {
return (*
this)[0]; }
65 constexpr const T*
elems()
const {
return data_ ? data_->
elems :
nullptr; }
70 if (*
this == other)
return true;
71 if (!*
this || !other)
return false;
73 for (
auto ai = this->
begin(), ae = this->
end(), bi = other.
begin(), be = other.
end(); ai != ae && bi != be;) {
74 if (*ai == *bi)
return true;
76 if ((*ai)->gid() < (*bi)->gid())
94 constexpr auto begin() const noexcept {
return elems(); }
97 constexpr auto cend() const noexcept {
return end(); }
98 constexpr auto rbegin() const noexcept {
return std::reverse_iterator(
end()); }
99 constexpr auto rend() const noexcept {
return std::reverse_iterator(
begin()); }
101 constexpr auto crend() const noexcept {
return rend(); }
105 const Data* data_ =
nullptr;
108 friend class Pool<T>;
114template<
class T>
struct std::hash<
mim::PooledSet<T>> {
115 constexpr size_t operator()(
mim::PooledSet<T> set)
const {
return std::hash<uintptr_t>()((uintptr_t)set.data_); }
143 auto [data, state] = allocate(1);
144 data->elems[0] = elem;
145 return unify(data, state);
150 if (a == b || !b)
return a;
153 auto size = a.size() + b.
size();
154 auto [data, state] = allocate(size);
156 auto di = data->elems;
157 auto ai = a.begin(), ae = a.end(), bi = b.
begin(), be = b.
end();
159 *di = (*ai)->gid() < (*bi)->gid() ? *ai++ : *bi++;
161 while (ai != ae && bi != be)
162 if ((*ai)->gid() < (*bi)->gid())
163 copy_if_unique_and_inc(di, ai);
165 copy_if_unique_and_inc(di, bi);
168 while (ai != ae) copy_if_unique_and_inc(di, ai);
169 while (bi != be) copy_if_unique_and_inc(di, bi);
171 auto actual_size = std::distance(data->elems, di + 1);
172 data->size = actual_size;
173 return unify(data, state, size - actual_size);
181 if (!set)
return set;
183 if (i == set.
end())
return set;
185 auto size = set.
size() - 1;
188 auto [data, state] = allocate(size);
189 std::copy(i + 1, set.
end(), std::copy(set.
begin(), i, data->elems));
190 return unify(data, state);
196 swap(p1.arena_, p2.arena_);
197 swap(p1.pool_, p2.pool_);
201 std::pair<Data*, fe::Arena::State> allocate(
size_t size) {
202 auto bytes =
sizeof(Data) + size *
SizeOf<T>;
203 auto state = arena_.state();
204 auto buf = arena_.allocate(bytes);
205 auto data =
new (buf) Data(size);
206 return {data, state};
209 PooledSet<T> unify(Data* data, fe::Arena::State state,
size_t excess = 0) {
210 auto [i, ins] = pool_.emplace(data);
213 return PooledSet<T>(data);
216 arena_.deallocate(state);
217 return PooledSet<T>(*i);
220 void copy_if_unique_and_inc(T*& i,
const T*& ai) {
221 if ((*i)->gid() != (*ai)->gid()) *++i = *ai;
226 absl::flat_hash_set<const Data*, absl::Hash<const Data*>,
typename Data::Equal> pool_;
Maintains PooledSets within a fe::Arena and unifies them in a absl::flat_hash_set.
PooledSet< T > merge(PooledSet< T > a, PooledSet< T > b)
Yields .
PooledSet< T > erase(PooledSet< T > set, const T &elem)
Yields .
friend void swap(Pool &p1, Pool &p2) noexcept
PooledSet< T > create(T elem)
Pool(const Pool &)=delete
PooledSet< T > insert(PooledSet< T > a, const T &elem)
Yields .
Pool & operator=(const Pool &)=delete
Ordered set maintained in a consecutive buffer and unified in Pool.
constexpr auto cend() const noexcept
constexpr bool operator==(PooledSet< T > other) const noexcept
constexpr bool operator!=(PooledSet< T > other) const noexcept
constexpr auto crbegin() const noexcept
constexpr auto end() const noexcept
constexpr size_t size() const noexcept
constexpr const T & operator[](size_t i) const
constexpr auto crend() const noexcept
constexpr PooledSet() noexcept=default
constexpr bool contains(const T &elem) const
constexpr auto begin() const noexcept
constexpr auto rbegin() const noexcept
friend H AbslHashValue(H h, PooledSet< T > set)
constexpr bool empty() const noexcept
constexpr const T * elems() const
constexpr void clear() noexcept
constexpr auto rend() const noexcept
constexpr auto cbegin() const noexcept
constexpr const T & front() const
bool intersects(PooledSet< T > other)
Is ?
static constexpr size_t SizeOf
I binary_find(I begin, I end, T val, Cmp cmp)
constexpr bool operator()(const Data *d1, const Data *d2) const
friend constexpr H AbslHashValue(H h, const Data *d)
constexpr Data() noexcept=default