tag/Pool: use class IntrusiveForwardList
This commit is contained in:
parent
b35e8a588f
commit
76bdfabcc5
|
@ -4,6 +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/VarSize.hxx"
|
#include "util/VarSize.hxx"
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
@ -17,35 +18,36 @@
|
||||||
Mutex tag_pool_lock;
|
Mutex tag_pool_lock;
|
||||||
|
|
||||||
struct TagPoolSlot {
|
struct TagPoolSlot {
|
||||||
TagPoolSlot *next;
|
IntrusiveForwardListHook list_hook;
|
||||||
uint8_t ref = 1;
|
uint8_t ref = 1;
|
||||||
TagItem item;
|
TagItem item;
|
||||||
|
|
||||||
static constexpr unsigned MAX_REF = std::numeric_limits<decltype(ref)>::max();
|
static constexpr unsigned MAX_REF = std::numeric_limits<decltype(ref)>::max();
|
||||||
|
|
||||||
TagPoolSlot(TagPoolSlot *_next, TagType type,
|
TagPoolSlot(TagType type,
|
||||||
std::string_view value) noexcept
|
std::string_view value) noexcept {
|
||||||
:next(_next) {
|
|
||||||
item.type = type;
|
item.type = type;
|
||||||
*std::copy(value.begin(), value.end(), item.value) = 0;
|
*std::copy(value.begin(), value.end(), item.value) = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static TagPoolSlot *Create(TagPoolSlot *_next, TagType type,
|
static TagPoolSlot *Create(TagType type,
|
||||||
std::string_view value) noexcept;
|
std::string_view value) noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
TagPoolSlot *
|
TagPoolSlot *
|
||||||
TagPoolSlot::Create(TagPoolSlot *_next, TagType type,
|
TagPoolSlot::Create(TagType type,
|
||||||
std::string_view value) noexcept
|
std::string_view value) noexcept
|
||||||
{
|
{
|
||||||
TagPoolSlot *dummy;
|
TagPoolSlot *dummy;
|
||||||
return NewVarSize<TagPoolSlot>(sizeof(dummy->item.value),
|
return NewVarSize<TagPoolSlot>(sizeof(dummy->item.value),
|
||||||
value.size() + 1,
|
value.size() + 1,
|
||||||
_next, type,
|
type,
|
||||||
value);
|
value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::array<TagPoolSlot *, 16127> slots;
|
static std::array<IntrusiveForwardList<TagPoolSlot,
|
||||||
|
IntrusiveForwardListMemberHookTraits<&TagPoolSlot::list_hook>>,
|
||||||
|
16127> slots;
|
||||||
|
|
||||||
static inline unsigned
|
static inline unsigned
|
||||||
calc_hash(TagType type, std::string_view p) noexcept
|
calc_hash(TagType type, std::string_view p) noexcept
|
||||||
|
@ -77,34 +79,37 @@ tag_item_to_slot(TagItem *item) noexcept
|
||||||
return &ContainerCast(*item, &TagPoolSlot::item);
|
return &ContainerCast(*item, &TagPoolSlot::item);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline TagPoolSlot **
|
static inline auto &
|
||||||
tag_value_slot_p(TagType type, std::string_view value) noexcept
|
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 TagPoolSlot **
|
static inline auto &
|
||||||
tag_value_slot_p(TagType type, const char *value) noexcept
|
tag_value_list(TagType type, const char *value) noexcept
|
||||||
{
|
{
|
||||||
return &slots[calc_hash(type, value) % slots.size()];
|
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 slot_p = tag_value_slot_p(type, value);
|
auto &list = tag_value_list(type, value);
|
||||||
for (auto slot = *slot_p; slot != nullptr; slot = slot->next) {
|
|
||||||
if (slot->item.type == type &&
|
for (auto i = list.before_begin(), n = std::next(i); n != list.end(); i = n) {
|
||||||
value == slot->item.value &&
|
auto &slot = *n++;
|
||||||
slot->ref < TagPoolSlot::MAX_REF) {
|
|
||||||
assert(slot->ref > 0);
|
if (slot.item.type == type &&
|
||||||
++slot->ref;
|
value == slot.item.value &&
|
||||||
return &slot->item;
|
slot.ref < TagPoolSlot::MAX_REF) {
|
||||||
|
assert(slot.ref > 0);
|
||||||
|
++slot.ref;
|
||||||
|
return &slot.item;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto slot = TagPoolSlot::Create(*slot_p, type, value);
|
auto slot = TagPoolSlot::Create(type, value);
|
||||||
*slot_p = slot;
|
list.push_front(*slot);
|
||||||
return &slot->item;
|
return &slot->item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,21 +134,22 @@ tag_pool_dup_item(TagItem *item) noexcept
|
||||||
void
|
void
|
||||||
tag_pool_put_item(TagItem *item) noexcept
|
tag_pool_put_item(TagItem *item) noexcept
|
||||||
{
|
{
|
||||||
TagPoolSlot **slot_p, *slot;
|
TagPoolSlot *const slot = tag_item_to_slot(item);
|
||||||
|
|
||||||
slot = tag_item_to_slot(item);
|
|
||||||
assert(slot->ref > 0);
|
assert(slot->ref > 0);
|
||||||
--slot->ref;
|
--slot->ref;
|
||||||
|
|
||||||
if (slot->ref > 0)
|
if (slot->ref > 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (slot_p = tag_value_slot_p(item->type, item->value);
|
auto &list = tag_value_list(item->type, item->value);
|
||||||
*slot_p != slot;
|
for (auto i = list.before_begin(), n = std::next(i);; i = n) {
|
||||||
slot_p = &(*slot_p)->next) {
|
assert(n != list.end());
|
||||||
assert(*slot_p != nullptr);
|
auto &s = *n++;
|
||||||
}
|
|
||||||
|
|
||||||
*slot_p = slot->next;
|
if (&s == slot) {
|
||||||
DeleteVarSize(slot);
|
list.erase_after(i);
|
||||||
|
DeleteVarSize(slot);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue