summaryrefslogtreecommitdiff
path: root/src/shared_string.hh
diff options
context:
space:
mode:
Diffstat (limited to 'src/shared_string.hh')
-rw-r--r--src/shared_string.hh68
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);