diff options
Diffstat (limited to 'src/shared_string.hh')
| -rw-r--r-- | src/shared_string.hh | 68 |
1 files changed, 31 insertions, 37 deletions
diff --git a/src/shared_string.hh b/src/shared_string.hh index ffd8bf04..b3906ea3 100644 --- a/src/shared_string.hh +++ b/src/shared_string.hh @@ -13,61 +13,55 @@ namespace Kakoune struct StringData : UseMemoryDomain<MemoryDomain::SharedString> { - int refcount; - int length; + uint32_t refcount; + const int length; - StringData(int ref, int len) : refcount(ref), length(len) {} - - [[gnu::always_inline]] - char* data() { return reinterpret_cast<char*>(this + 1); } [[gnu::always_inline]] const char* data() const { return reinterpret_cast<const char*>(this + 1); } [[gnu::always_inline]] StringView strview() const { return {data(), length}; } +private: + StringData(int len) : refcount(0), length(len) {} + + static constexpr uint32_t interned_flag = 1 << 31; + static constexpr uint32_t refcount_mask = ~interned_flag; + struct PtrPolicy { static void inc_ref(StringData* r, void*) noexcept { ++r->refcount; } - static void dec_ref(StringData* r, void*) noexcept { if (--r->refcount == 0) destroy(r); } + static void dec_ref(StringData* r, void*) noexcept + { + if ((--r->refcount & refcount_mask) == 0) + { + if (r->refcount & interned_flag) + Registry::instance().remove(r->strview()); + StringData::operator delete(r, sizeof(StringData) + r->length + 1); + } + } static void ptr_moved(StringData*, void*, void*) noexcept {} }; - static RefPtr<StringData, PtrPolicy> create(ArrayView<const StringView> strs) - { - const int len = std::accumulate(strs.begin(), strs.end(), 0, - [](int l, StringView s) - { return l + (int)s.length(); }); - void* ptr = StringData::operator new(sizeof(StringData) + len + 1); - auto* res = new (ptr) StringData(0, len); - auto* data = res->data(); - for (auto& str : strs) - { - memcpy(data, str.begin(), (size_t)str.length()); - data += (int)str.length(); - } - res->data()[len] = 0; - return RefPtr<StringData, PtrPolicy>{res}; - } +public: + using Ptr = RefPtr<StringData, PtrPolicy>; - static void destroy(StringData* s) + class Registry : public Singleton<Registry> { - StringData::operator delete(s, sizeof(StringData) + s->length + 1); - } -}; + public: + void debug_stats() const; + Ptr intern(StringView str); + void remove(StringView str); -using StringDataPtr = RefPtr<StringData, StringData::PtrPolicy>; - -class StringRegistry : public Singleton<StringRegistry> -{ -public: - void debug_stats() const; - StringDataPtr intern(StringView str); - void purge_unused(); + private: + UnorderedMap<StringView, StringData*, MemoryDomain::SharedString> m_strings; + }; -private: - UnorderedMap<StringView, StringDataPtr, MemoryDomain::SharedString> m_strings; + static Ptr create(ArrayView<const StringView> strs); }; +using StringDataPtr = StringData::Ptr; +using StringRegistry = StringData::Registry; + inline StringDataPtr intern(StringView str) { return StringRegistry::instance().intern(str); |
