chore(DenseSet): Some code reorder without change in functionality. (#338)
This commit is contained in:
parent
b74d65dee4
commit
2686b9316a
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
Loading…
Reference in New Issue