Files
clice/include/Support/ObjectPool.h
2025-11-30 15:21:27 +08:00

225 lines
5.0 KiB
C++

#pragma once
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Allocator.h"
namespace clice {
class StringSet {
public:
using ID = std::uint32_t;
StringSet(llvm::BumpPtrAllocator& allocator) : allocator(allocator) {
strings.emplace_back();
}
StringSet(const StringSet&) = delete;
StringSet(StringSet&&) = delete;
StringSet& operator=(const StringSet&) = delete;
StringSet& operator=(StringSet&&) = delete;
~StringSet() = default;
ID get(llvm::StringRef s) {
if(s.empty()) {
return ID(0);
}
auto [it, success] = cache.try_emplace(s, ID(0));
if(!success) {
return it->second;
}
const auto size = s.size();
auto p = allocator.Allocate<char>(size + 1);
std::memcpy(p, s.data(), size);
p[size] = '\0';
it->first = llvm::StringRef(p, size);
it->second = ID(strings.size());
strings.emplace_back(it->first);
return it->second;
}
llvm::StringRef get(ID id) {
assert(id < strings.size());
return strings[id];
}
llvm::StringRef save(llvm::StringRef s) {
return get(get(s));
}
private:
llvm::BumpPtrAllocator& allocator;
std::vector<llvm::StringRef> strings;
llvm::DenseMap<llvm::StringRef, ID> cache;
};
template <typename T>
struct object_ptr {
T* ptr = nullptr;
object_ptr() noexcept = default;
object_ptr(std::nullptr_t) noexcept : ptr(nullptr) {}
explicit object_ptr(T* p) noexcept : ptr(p) {}
T& operator*() const noexcept {
return *ptr;
}
T* operator->() const noexcept {
return ptr;
}
explicit operator bool() const noexcept {
return ptr != nullptr;
}
std::strong_ordering operator<=>(const object_ptr&) const = default;
};
template <typename T>
object_ptr(T*) -> object_ptr<T>;
template <typename T>
class ObjectSet {
public:
using ID = std::uint32_t;
ObjectSet(llvm::BumpPtrAllocator& allocator) : allocator(allocator) {}
ObjectSet(const ObjectSet&) = delete;
ObjectSet(ObjectSet&&) = delete;
ObjectSet& operator=(const ObjectSet&) = delete;
ObjectSet& operator=(ObjectSet&&) = delete;
~ObjectSet() {
if constexpr(!std::is_trivially_destructible_v<T>) {
for(auto object: objects) {
if(object) {
std::destroy_at(object.ptr);
}
}
for(auto& [object, _]: removed) {
if(object) {
std::destroy_at(object.ptr);
}
}
}
}
ID get(const T& object) {
auto [it, success] = cache.try_emplace(object_ptr(const_cast<T*>(&object)), ID(0));
if(!success) {
return it->second;
}
if(!removed.empty()) [[unlikely]] {
auto [o, id] = removed.pop_back_val();
/// Reuse the old memory
std::destroy_at(o.ptr);
new (o.ptr) T(object);
it->first = o;
it->second = id;
/// Resume the object id.
objects[id] = o;
} else {
/// Alloc the new memory.
auto p = allocator.Allocate<T>(1);
p = new (p) T(object);
it->first = object_ptr<T>{p};
it->second = ID(objects.size());
objects.emplace_back(p);
}
return it->second;
}
object_ptr<T> get(ID id) {
assert(id < objects.size());
return objects[id];
}
object_ptr<T> save(const T& object) {
return this->get(this->get(object));
}
void remove(object_ptr<T> object) {
auto it = cache.find(object_ptr<T>(object.ptr));
if(it == cache.end()) {
return;
}
auto id = it->second;
removed.emplace_back(object, id);
cache.erase(it);
objects[id] = nullptr;
}
private:
llvm::BumpPtrAllocator& allocator;
std::vector<object_ptr<T>> objects;
llvm::SmallVector<std::pair<object_ptr<T>, ID>> removed;
llvm::DenseMap<object_ptr<T>, ID> cache;
};
} // namespace clice
namespace llvm {
template <typename T>
struct DenseMapInfo<clice::object_ptr<T>> {
using U = std::remove_cvref_t<T>;
using O = clice::object_ptr<T>;
inline static O getEmptyKey() {
return O(DenseMapInfo<U*>::getEmptyKey());
}
inline static O getTombstoneKey() {
return O(DenseMapInfo<U*>::getTombstoneKey());
}
inline static unsigned getHashValue(O value) {
return DenseMapInfo<U>::getHashValue(*value);
}
inline static bool isEqual(O lhs, O rhs) {
if(lhs == rhs) {
return true;
};
const O Empty = getEmptyKey();
const O Tombstone = getTombstoneKey();
if(lhs == Empty || rhs == Empty || lhs == Tombstone || rhs == Tombstone) {
return false;
}
return DenseMapInfo<U>::isEqual(*lhs, *rhs);
}
};
} // namespace llvm