Pioneer
Loading...
Searching...
No Matches
StringName.h
Go to the documentation of this file.
1// Copyright © 2008-2023 Pioneer Developers. See AUTHORS.txt for details
2// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
3
4#pragma once
5
6#include "StringHash.h"
7#include "profiler/Profiler.h"
8
9#include <atomic>
10#include <string_view>
11#include <type_traits>
12#include <vector>
13
14/*
15 * Lightweight immutable refcounted string class. Internally stores string data
16 * in the string object or in a thread-local hashtable for storage efficiency.
17 */
19 static constexpr uint32_t MAX_SSO_SIZE = 15;
20
21public:
23 m_hash(0),
24 m_size(0),
25 m_str{} {}
26
27 StringName(std::string_view s, uint32_t hash = 0);
28 StringName(const StringName &rhs) :
29 StringName() { *this = rhs; }
30 StringName &operator=(const StringName &rhs);
32 StringName() { *this = std::move(rhs); };
34
36 {
37 if (m_size > MAX_SSO_SIZE)
38 m_str.ptr->unref();
39 m_size = 0;
40 m_hash = 0;
41 }
42
43 uint32_t hash() const { return m_hash; }
44 size_t size() const { return m_size; }
45 const char *c_str() const { return m_size > MAX_SSO_SIZE ? m_str.ptr->get() : m_str.data; }
46 std::string_view sv() const { return { c_str(), size() }; }
47
48 operator std::string_view() const { return sv(); }
49 operator bool() const { return m_size; }
50
51 bool operator==(std::string_view rhs) const { return sv() == rhs; }
52 bool operator!=(std::string_view rhs) const { return !(*this == rhs); }
53 bool operator<(std::string_view rhs) const { return sv() < rhs; }
54
55 bool operator==(const StringName &rhs) const { return hash() == rhs.hash(); }
56 bool operator!=(const StringName &rhs) const { return !(*this == rhs); }
57 bool operator<(const StringName &rhs) const { return sv() < rhs.sv(); }
58
59private:
60 friend class StringTable;
61
62 struct StringData {
63 mutable std::atomic<uint32_t> refcount;
64 char *get() { return reinterpret_cast<char *>(&this[1]); }
65
66 uint32_t ref() const { return refcount.fetch_add(1) + 1; }
67 uint32_t unref() const { return refcount.fetch_sub(1) - 1; }
68 uint32_t get_ref() const { return refcount.load(); }
69 };
70
71 // handle interning and de-duplicating the string memory
72 static StringData *make_data(const char *s, uint32_t size, uint32_t hash);
73
74 uint32_t m_hash;
75 uint32_t m_size;
76 union { // small string optimization
77 StringData *ptr;
78 char data[16];
79 } m_str;
80};
81
82/*
83 * Thread-local hash table for efficient storage of immutable strings.
84 * StringTable uses a power-of-two based robin-hood hash table to keep
85 * indexing overhead as small as possible.
86 */
88public:
89 using Data = StringName::StringData *;
90
91 StringTable(uint32_t size) :
92 keys(size),
93 dist(size),
94 values(size),
95 entries(0) {}
96
97 static StringTable *Get();
98
99 size_t Size() const { return entries; }
100 size_t Capacity() const { return keys.size(); }
101
102 Data *Find(uint32_t key);
103 Data *Create(uint32_t key);
104
105 Data &FindOrCreate(uint32_t key)
106 {
107 if (auto *ptr = Find(key))
108 return *ptr;
109
110 return *Create(key);
111 }
112
113 void Erase(uint32_t key);
114
115 // Quiescent memory reclamation - call this function every 30s or so
116 // from the owning thread
117 void Reclaim(bool force = false);
118
119private:
120 void Grow();
121
122 std::vector<uint32_t> keys;
123 std::vector<uint8_t> dist;
124 std::vector<Data> values;
125 uint32_t entries;
126 Profiler::Clock m_reclaimClock;
127};
128
129inline StringName operator""_name(const char *c, size_t l) { return StringName(std::string_view(c, l)); }
Definition StringName.h:18
std::string_view sv() const
Definition StringName.h:46
char data[16]
Definition StringName.h:78
StringName & operator=(const StringName &rhs)
Definition StringName.cpp:28
bool operator==(std::string_view rhs) const
Definition StringName.h:51
bool operator==(const StringName &rhs) const
Definition StringName.h:55
StringData * ptr
Definition StringName.h:77
~StringName()
Definition StringName.h:35
bool operator!=(const StringName &rhs) const
Definition StringName.h:56
StringName(const StringName &rhs)
Definition StringName.h:28
StringName(StringName &&rhs)
Definition StringName.h:31
bool operator<(const StringName &rhs) const
Definition StringName.h:57
bool operator<(std::string_view rhs) const
Definition StringName.h:53
size_t size() const
Definition StringName.h:44
const char * c_str() const
Definition StringName.h:45
bool operator!=(std::string_view rhs) const
Definition StringName.h:52
StringName()
Definition StringName.h:22
uint32_t hash() const
Definition StringName.h:43
Definition StringName.h:87
void Reclaim(bool force=false)
Definition StringName.cpp:161
static StringTable * Get()
Definition StringName.cpp:205
size_t Size() const
Definition StringName.h:99
Data * Create(uint32_t key)
Definition StringName.cpp:89
StringTable(uint32_t size)
Definition StringName.h:91
Data & FindOrCreate(uint32_t key)
Definition StringName.h:105
Data * Find(uint32_t key)
Definition StringName.cpp:71
StringName::StringData * Data
Definition StringName.h:89
size_t Capacity() const
Definition StringName.h:100
void Erase(uint32_t key)
Definition StringName.cpp:127