Pioneer
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  */
18 class StringName {
19  static constexpr uint32_t MAX_SSO_SIZE = 15;
20 
21 public:
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 
59 private:
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  */
87 class StringTable {
88 public:
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 
119 private:
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 
129 inline 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
const char * c_str() const
Definition: StringName.h:45
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
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 * Find(uint32_t key)
Definition: StringName.cpp:71
Data & FindOrCreate(uint32_t key)
Definition: StringName.h:105
StringName::StringData * Data
Definition: StringName.h:89
size_t Capacity() const
Definition: StringName.h:100
void Erase(uint32_t key)
Definition: StringName.cpp:127