tag/Pool: use doubly-linked list
This adds some memory overhead but eliminates the linear search from tag_pool_put_item().
This commit is contained in:
parent
b896711fc6
commit
44beae519d
|
@ -4,7 +4,7 @@
|
||||||
#include "Pool.hxx"
|
#include "Pool.hxx"
|
||||||
#include "Item.hxx"
|
#include "Item.hxx"
|
||||||
#include "util/Cast.hxx"
|
#include "util/Cast.hxx"
|
||||||
#include "util/IntrusiveForwardList.hxx"
|
#include "util/IntrusiveList.hxx"
|
||||||
#include "util/VarSize.hxx"
|
#include "util/VarSize.hxx"
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
@ -18,7 +18,7 @@
|
||||||
Mutex tag_pool_lock;
|
Mutex tag_pool_lock;
|
||||||
|
|
||||||
struct TagPoolSlot {
|
struct TagPoolSlot {
|
||||||
IntrusiveForwardListHook list_hook;
|
IntrusiveListHook<IntrusiveHookMode::NORMAL> list_hook;
|
||||||
uint8_t ref = 1;
|
uint8_t ref = 1;
|
||||||
TagItem item;
|
TagItem item;
|
||||||
|
|
||||||
|
@ -45,8 +45,8 @@ TagPoolSlot::Create(TagType type,
|
||||||
value);
|
value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::array<IntrusiveForwardList<TagPoolSlot,
|
static std::array<IntrusiveList<TagPoolSlot,
|
||||||
IntrusiveForwardListMemberHookTraits<&TagPoolSlot::list_hook>>,
|
IntrusiveListMemberHookTraits<&TagPoolSlot::list_hook>>,
|
||||||
16127> slots;
|
16127> slots;
|
||||||
|
|
||||||
static inline unsigned
|
static inline unsigned
|
||||||
|
@ -60,19 +60,6 @@ calc_hash(TagType type, std::string_view p) noexcept
|
||||||
return hash ^ type;
|
return hash ^ type;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned
|
|
||||||
calc_hash(TagType type, const char *p) noexcept
|
|
||||||
{
|
|
||||||
unsigned hash = 5381;
|
|
||||||
|
|
||||||
assert(p != nullptr);
|
|
||||||
|
|
||||||
while (*p != 0)
|
|
||||||
hash = (hash << 5) + hash + *p++;
|
|
||||||
|
|
||||||
return hash ^ type;
|
|
||||||
}
|
|
||||||
|
|
||||||
static constexpr TagPoolSlot *
|
static constexpr TagPoolSlot *
|
||||||
tag_item_to_slot(TagItem *item) noexcept
|
tag_item_to_slot(TagItem *item) noexcept
|
||||||
{
|
{
|
||||||
|
@ -85,20 +72,12 @@ tag_value_list(TagType type, std::string_view value) noexcept
|
||||||
return slots[calc_hash(type, value) % slots.size()];
|
return slots[calc_hash(type, value) % slots.size()];
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline auto &
|
|
||||||
tag_value_list(TagType type, const char *value) noexcept
|
|
||||||
{
|
|
||||||
return slots[calc_hash(type, value) % slots.size()];
|
|
||||||
}
|
|
||||||
|
|
||||||
TagItem *
|
TagItem *
|
||||||
tag_pool_get_item(TagType type, std::string_view value) noexcept
|
tag_pool_get_item(TagType type, std::string_view value) noexcept
|
||||||
{
|
{
|
||||||
auto &list = tag_value_list(type, value);
|
auto &list = tag_value_list(type, value);
|
||||||
|
|
||||||
for (auto i = list.before_begin(), n = std::next(i); n != list.end(); i = n) {
|
for (auto &slot : list) {
|
||||||
auto &slot = *n++;
|
|
||||||
|
|
||||||
if (slot.item.type == type &&
|
if (slot.item.type == type &&
|
||||||
value == slot.item.value &&
|
value == slot.item.value &&
|
||||||
slot.ref < TagPoolSlot::MAX_REF) {
|
slot.ref < TagPoolSlot::MAX_REF) {
|
||||||
|
@ -141,18 +120,6 @@ tag_pool_put_item(TagItem *item) noexcept
|
||||||
if (slot->ref > 0)
|
if (slot->ref > 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto &list = tag_value_list(item->type, item->value);
|
slot->list_hook.unlink();
|
||||||
for (auto i = list.before_begin();;) {
|
DeleteVarSize(slot);
|
||||||
const auto n = std::next(i);
|
|
||||||
auto &s = *n;
|
|
||||||
assert(i != list.end());
|
|
||||||
|
|
||||||
if (&s == slot) {
|
|
||||||
list.erase_after(i);
|
|
||||||
DeleteVarSize(slot);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
i = n;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue