2014-10-01 01:20:12 +02:00
|
|
|
#include "interned_string.hh"
|
2015-01-13 14:48:16 +01:00
|
|
|
#include "debug.hh"
|
2014-10-01 01:20:12 +02:00
|
|
|
|
|
|
|
namespace Kakoune
|
|
|
|
{
|
|
|
|
|
2015-01-13 14:48:16 +01:00
|
|
|
void StringRegistry::debug_stats() const
|
|
|
|
{
|
|
|
|
write_debug("Interned Strings stats:");
|
|
|
|
write_debug(" slots: " + to_string(m_storage.size()) + " allocated, " + to_string(m_free_slots.size()) + " free");
|
|
|
|
size_t total_refcount = 0;
|
|
|
|
size_t total_size = 0;
|
|
|
|
size_t count = 0;
|
|
|
|
for (auto& st : m_storage)
|
|
|
|
{
|
|
|
|
if (st.refcount == 0)
|
|
|
|
continue;
|
|
|
|
total_refcount += st.refcount;
|
|
|
|
total_size += st.data.size();
|
|
|
|
++count;
|
|
|
|
}
|
|
|
|
write_debug(" data size: " + to_string(total_size) + ", mean: " + to_string((float)total_size/count));
|
|
|
|
write_debug(" refcounts: " + to_string(total_refcount) + ", mean: " + to_string((float)total_refcount/count));
|
|
|
|
}
|
|
|
|
|
2014-10-01 01:20:12 +02:00
|
|
|
InternedString StringRegistry::acquire(StringView str)
|
|
|
|
{
|
|
|
|
auto it = m_slot_map.find(str);
|
|
|
|
if (it == m_slot_map.end())
|
|
|
|
{
|
2015-01-13 14:58:11 +01:00
|
|
|
Slot slot;
|
2014-10-01 01:20:12 +02:00
|
|
|
if (not m_free_slots.empty())
|
|
|
|
{
|
|
|
|
slot = m_free_slots.back();
|
|
|
|
m_free_slots.pop_back();
|
2014-12-30 12:56:01 +01:00
|
|
|
kak_assert(m_storage[slot].refcount == 0);
|
|
|
|
m_storage[slot] = DataAndRefCount{{str.begin(), str.end()}, 1};
|
2014-10-01 01:20:12 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
slot = m_storage.size();
|
2014-12-30 12:56:01 +01:00
|
|
|
m_storage.push_back({{str.begin(), str.end()}, 1});
|
2014-10-01 01:20:12 +02:00
|
|
|
}
|
|
|
|
// Create a new string view that point to the storage data
|
2014-12-30 12:56:01 +01:00
|
|
|
StringView storage_view{m_storage[slot].data.data(), (int)m_storage[slot].data.size()};
|
2014-10-01 01:20:12 +02:00
|
|
|
m_slot_map[storage_view] = slot;
|
|
|
|
|
2014-10-05 11:20:50 +02:00
|
|
|
return InternedString{storage_view, slot};
|
2014-10-01 01:20:12 +02:00
|
|
|
}
|
|
|
|
|
2015-01-13 14:58:11 +01:00
|
|
|
Slot slot = it->second;
|
2014-10-07 20:07:05 +02:00
|
|
|
auto& data = m_storage[slot];
|
2014-12-30 12:56:01 +01:00
|
|
|
++data.refcount;
|
|
|
|
return {{data.data.data(), (int)data.data.size()}, slot};
|
2014-10-01 01:20:12 +02:00
|
|
|
}
|
|
|
|
|
2015-01-13 14:58:11 +01:00
|
|
|
void StringRegistry::acquire(Slot slot)
|
2014-10-01 01:20:12 +02:00
|
|
|
{
|
2014-10-05 11:20:50 +02:00
|
|
|
kak_assert(slot < m_storage.size());
|
2014-12-30 12:56:01 +01:00
|
|
|
kak_assert(m_storage[slot].refcount > 0);
|
|
|
|
++m_storage[slot].refcount;
|
2014-10-05 11:20:50 +02:00
|
|
|
}
|
2014-10-01 01:20:12 +02:00
|
|
|
|
2015-01-13 14:58:11 +01:00
|
|
|
void StringRegistry::release(Slot slot) noexcept
|
2014-10-05 11:20:50 +02:00
|
|
|
{
|
2014-12-30 12:56:01 +01:00
|
|
|
kak_assert(m_storage[slot].refcount > 0);
|
|
|
|
if (--m_storage[slot].refcount == 0)
|
2014-10-01 01:20:12 +02:00
|
|
|
{
|
|
|
|
m_free_slots.push_back(slot);
|
2015-01-07 20:29:31 +01:00
|
|
|
auto& data = m_storage[slot].data;
|
2014-10-05 11:20:50 +02:00
|
|
|
auto it = m_slot_map.find(StringView{data.data(), (int)data.size()});
|
|
|
|
kak_assert(it != m_slot_map.end());
|
2014-10-01 01:20:12 +02:00
|
|
|
m_slot_map.erase(it);
|
2015-01-07 20:29:31 +01:00
|
|
|
data = Vector<char, MemoryDomain::InternedString>{};
|
2014-10-01 01:20:12 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|