chore(DenseSet): Some code reorder without change in functionality. (#338)

This commit is contained in:
Roman Gershman 2022-09-29 16:13:55 +03:00 committed by GitHub
parent b74d65dee4
commit 2686b9316a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 163 additions and 166 deletions

View File

@ -108,18 +108,6 @@ auto DenseSet::Unlink(DenseSet::DensePtr* node) -> DensePtr {
return ret;
}
// updates *node with the next item
void* DenseSet::UnlinkAndFree(DenseSet::DensePtr* node) {
DensePtr unlinked = Unlink(node);
void* ret = unlinked.GetObject();
if (unlinked.IsLink()) {
FreeLink(unlinked);
}
return ret;
}
void DenseSet::ClearInternal() {
for (auto it = entries_.begin(); it != entries_.end(); ++it) {
while (!it->IsEmpty()) {
@ -130,6 +118,14 @@ void DenseSet::ClearInternal() {
entries_.clear();
}
bool DenseSet::Equal(DensePtr dptr, const void* ptr) const {
if (dptr.IsEmpty()) {
return false;
}
return ObjEqual(dptr.GetObject(), ptr);
}
auto DenseSet::FindEmptyAround(uint32_t bid) -> ChainVectorIterator {
if (entries_[bid].IsEmpty()) {
return entries_.begin() + bid;
@ -271,7 +267,7 @@ bool DenseSet::AddInternal(void* ptr) {
auto DenseSet::Find(const void* ptr, uint32_t bid) const -> const DensePtr* {
const DensePtr* curr = &entries_[bid];
if (!curr->IsEmpty() && Equal(*curr, ptr)) {
if (Equal(*curr, ptr)) {
return curr;
}
@ -298,31 +294,26 @@ auto DenseSet::Find(const void* ptr, uint32_t bid) const -> const DensePtr* {
return nullptr;
}
// Same idea as FindAround but provide the const guarantee
bool DenseSet::ContainsInternal(const void* ptr) const {
uint32_t bid = BucketId(ptr);
return Find(ptr, bid) != nullptr;
}
void* DenseSet::Delete(DensePtr* ptr) {
void* ret = nullptr;
void* DenseSet::EraseInternal(void* ptr) {
uint32_t bid = BucketId(ptr);
auto found = Find(ptr, bid);
if (found == nullptr) {
return nullptr;
}
if (found->IsLink()) {
--num_chain_entries_;
} else {
DCHECK(found->IsObject());
if (ptr->IsObject()) {
ret = ptr->Raw();
ptr->Reset();
--num_used_buckets_;
} else {
DCHECK(ptr->IsLink());
DenseLinkKey* link = ptr->AsLink();
ret = link->Raw();
*ptr = link->next;
--num_chain_entries_;
mr()->deallocate(link, sizeof(DenseLinkKey), alignof(DenseLinkKey));
}
obj_malloc_used_ -= ObjectAllocSize(ptr);
void* ret = UnlinkAndFree(found);
obj_malloc_used_ -= ObjectAllocSize(ret);
--size_;
return ret;
}
@ -402,4 +393,15 @@ uint32_t DenseSet::Scan(uint32_t cursor, const ItemCb& cb) const {
return entries_idx << (32 - capacity_log_);
}
auto DenseSet::NewLink(void* data, DensePtr next) -> DenseLinkKey* {
LinkAllocator la(mr());
DenseLinkKey* lk = la.allocate(1);
la.construct(lk);
lk->next = next;
lk->SetObject(data);
return lk;
}
} // namespace dfly

View File

@ -36,28 +36,6 @@ namespace dfly {
// static_assert(sizeof(dictEntry) == 24);
class DenseSet {
public:
explicit DenseSet(std::pmr::memory_resource* mr = std::pmr::get_default_resource());
virtual ~DenseSet();
protected:
// Virtual functions to be implemented for generic data
virtual uint64_t Hash(const void*) const = 0;
virtual bool Equal(const void*, const void*) const = 0;
virtual size_t ObjectAllocSize(const void*) const = 0;
bool AddInternal(void*);
bool ContainsInternal(const void*) const;
void* EraseInternal(void*);
void* PopInternal();
// Note this does not free any dynamic allocations done by derived classes, that a DensePtr
// in the set may point to. This function only frees the allocated DenseLinkKeys created by
// DenseSet. All data allocated by a derived class should be freed before calling this
void ClearInternal();
private:
DenseSet(const DenseSet&) = delete;
DenseSet& operator=(DenseSet&) = delete;
struct DenseLinkKey;
// we can assume that high 12 bits of user address space
@ -82,7 +60,7 @@ class DenseSet {
}
bool IsLink() const {
return (uptr() & kLinkBit) == kLinkBit;
return (uptr() & kLinkBit) != 0;
}
bool IsEmpty() const {
@ -173,87 +151,10 @@ class DenseSet {
using ChainVectorIterator = std::pmr::vector<DensePtr>::iterator;
using ChainVectorConstIterator = std::pmr::vector<DensePtr>::const_iterator;
bool Equal(const DensePtr dptr, const void* ptr) const {
if (dptr.IsEmpty()) {
return false;
}
return Equal(dptr.GetObject(), ptr);
}
std::pmr::memory_resource* mr() {
return entries_.get_allocator().resource();
}
uint32_t BucketId(uint64_t hash) const {
return hash >> (64 - capacity_log_);
}
uint32_t BucketId(const void* ptr) const {
return BucketId(Hash(ptr));
}
// return a ChainVectorIterator (a.k.a iterator) or end if there is an empty chain found
ChainVectorIterator FindEmptyAround(uint32_t bid);
void Grow();
// ============ Pseudo Linked List Functions for interacting with Chains ==================
size_t PushFront(ChainVectorIterator, void*);
void PushFront(ChainVectorIterator, DensePtr);
void* PopDataFront(ChainVectorIterator);
DensePtr PopPtrFront(ChainVectorIterator);
// Note this function will modify the iterator passed to it
// to point to the next node in the chain
DensePtr Unlink(DensePtr* node);
// Note this will only free the encapsulating DenseLinkKey and not
// the data it points to, this will be returned.
// This function will modify the iterator passed to it
// to point to the next node in the chain
void* UnlinkAndFree(DensePtr* node);
// ============ Pseudo Linked List in DenseSet end ==================
const DensePtr* Find(const void* ptr, uint32_t bid) const;
const DensePtr* Find(const void* ptr) const {
return Find(ptr, BucketId(ptr));
}
DensePtr* Find(const void* ptr, uint32_t bid) {
const DensePtr* ret = const_cast<const DenseSet*>(this)->Find(ptr, bid);
return const_cast<DensePtr*>(ret);
}
DensePtr* Find(const void* ptr) {
const DensePtr* ret = const_cast<const DenseSet*>(this)->Find(ptr);
return const_cast<DensePtr*>(ret);
}
inline DenseLinkKey* NewLink(void* data, DensePtr next) {
LinkAllocator la(mr());
DenseLinkKey* lk = la.allocate(1);
la.construct(lk);
lk->next = next;
lk->SetObject(data);
return lk;
}
inline void FreeLink(DensePtr link) {
// deallocate the link if it is no longer a link as it is now in an empty list
mr()->deallocate(link.AsLink(), sizeof(DenseLinkKey), alignof(DenseLinkKey));
}
std::pmr::vector<DensePtr> entries_;
size_t obj_malloc_used_ = 0;
uint32_t size_ = 0;
uint32_t num_chain_entries_ = 0;
uint32_t num_used_buckets_ = 0;
unsigned capacity_log_ = 0;
public:
explicit DenseSet(std::pmr::memory_resource* mr = std::pmr::get_default_resource());
virtual ~DenseSet();
size_t Size() const {
return size_;
}
@ -412,6 +313,99 @@ class DenseSet {
uint32_t Scan(uint32_t cursor, const ItemCb& cb) const;
void Reserve(size_t sz);
protected:
// Virtual functions to be implemented for generic data
virtual uint64_t Hash(const void* obj) const = 0;
virtual bool ObjEqual(const void* obj1, const void* obj2) const = 0;
virtual size_t ObjectAllocSize(const void* obj) const = 0;
void* EraseInternal(void* obj) {
DensePtr* found = Find(obj);
return found ? Delete(found) : nullptr;
}
bool AddInternal(void* obj);
bool ContainsInternal(const void* obj) const {
return Find(obj, BucketId(obj)) != nullptr;
}
void* PopInternal();
// Note this does not free any dynamic allocations done by derived classes, that a DensePtr
// in the set may point to. This function only frees the allocated DenseLinkKeys created by
// DenseSet. All data allocated by a derived class should be freed before calling this
void ClearInternal();
private:
DenseSet(const DenseSet&) = delete;
DenseSet& operator=(DenseSet&) = delete;
bool Equal(DensePtr dptr, const void* ptr) const;
std::pmr::memory_resource* mr() {
return entries_.get_allocator().resource();
}
uint32_t BucketId(uint64_t hash) const {
return hash >> (64 - capacity_log_);
}
uint32_t BucketId(const void* ptr) const {
return BucketId(Hash(ptr));
}
// return a ChainVectorIterator (a.k.a iterator) or end if there is an empty chain found
ChainVectorIterator FindEmptyAround(uint32_t bid);
void Grow();
// ============ Pseudo Linked List Functions for interacting with Chains ==================
size_t PushFront(ChainVectorIterator, void*);
void PushFront(ChainVectorIterator, DensePtr);
void* PopDataFront(ChainVectorIterator);
DensePtr PopPtrFront(ChainVectorIterator);
// Note this function will modify the iterator passed to it
// to point to the next node in the chain
DensePtr Unlink(DensePtr* node);
// ============ Pseudo Linked List in DenseSet end ==================
const DensePtr* Find(const void* ptr, uint32_t bid) const;
const DensePtr* Find(const void* ptr) const {
return Find(ptr, BucketId(ptr));
}
DensePtr* Find(const void* ptr, uint32_t bid) {
const DensePtr* ret = const_cast<const DenseSet*>(this)->Find(ptr, bid);
return const_cast<DensePtr*>(ret);
}
DensePtr* Find(const void* ptr) {
const DensePtr* ret = const_cast<const DenseSet*>(this)->Find(ptr);
return const_cast<DensePtr*>(ret);
}
DenseLinkKey* NewLink(void* data, DensePtr next);
inline void FreeLink(DensePtr link) {
// deallocate the link if it is no longer a link as it is now in an empty list
mr()->deallocate(link.AsLink(), sizeof(DenseLinkKey), alignof(DenseLinkKey));
}
void* Delete(DensePtr* ptr);
// We may update it during const operations due to expiry interactions.
std::pmr::vector<DensePtr> entries_;
size_t obj_malloc_used_ = 0;
uint32_t size_ = 0;
uint32_t num_chain_entries_ = 0;
uint32_t num_used_buckets_ = 0;
unsigned capacity_log_ = 0;
};
} // namespace dfly

View File

@ -9,25 +9,6 @@ extern "C" {
namespace dfly {
uint64_t StringSet::Hash(const void* ptr) const {
sds s = (sds)ptr;
return CompactObj::HashCode(std::string_view{s, sdslen(s)});
}
bool StringSet::Equal(const void* ptr1, const void* ptr2) const {
sds s1 = (sds)ptr1;
sds s2 = (sds)ptr2;
if (sdslen(s1) != sdslen(s2)) {
return false;
}
return sdslen(s1) == 0 || memcmp(s1, s2, sdslen(s1)) == 0;
}
size_t StringSet::ObjectAllocSize(const void* s1) const {
return zmalloc_usable_size(sdsAllocPtr((sds)s1));
}
bool StringSet::AddSds(sds s1) {
return AddInternal(s1);
}
@ -42,14 +23,14 @@ bool StringSet::Add(std::string_view s1) {
return true;
}
bool StringSet::EraseSds(sds s1) {
void* ret = EraseInternal(s1);
bool StringSet::EraseSds(sds str) {
void* ret = EraseInternal(str);
if (ret == nullptr) {
return false;
} else {
sdsfree((sds)ret);
return true;
}
sdsfree((sds)ret);
return true;
}
bool StringSet::Erase(std::string_view s1) {
@ -99,4 +80,23 @@ uint32_t StringSet::Scan(uint32_t cursor, const std::function<void(const sds)>&
return DenseSet::Scan(cursor, [func](const void* ptr) { func((sds)ptr); });
}
uint64_t StringSet::Hash(const void* ptr) const {
sds s = (sds)ptr;
return CompactObj::HashCode(std::string_view{s, sdslen(s)});
}
bool StringSet::ObjEqual(const void* ptr1, const void* ptr2) const {
sds s1 = (sds)ptr1;
sds s2 = (sds)ptr2;
if (sdslen(s1) != sdslen(s2)) {
return false;
}
return sdslen(s1) == 0 || memcmp(s1, s2, sdslen(s1)) == 0;
}
size_t StringSet::ObjectAllocSize(const void* s1) const {
return zmalloc_usable_size(sdsAllocPtr((sds)s1));
}
}; // namespace dfly

View File

@ -14,12 +14,6 @@ namespace dfly {
class StringSet : public DenseSet {
public:
uint64_t Hash(const void* ptr) const override;
bool Equal(const void* ptr1, const void* ptr2) const override;
size_t ObjectAllocSize(const void* s1) const override;
bool Add(std::string_view s1);
bool AddSds(sds s1);
@ -61,6 +55,13 @@ class StringSet : public DenseSet {
}
uint32_t Scan(uint32_t, const std::function<void(sds)>&) const;
protected:
uint64_t Hash(const void* ptr) const override;
bool ObjEqual(const void* ptr1, const void* ptr2) const override;
size_t ObjectAllocSize(const void* s1) const override;
};
} // end namespace dfly