13 template<
size_t nSize>
14 string_pool<nSize>::string_pool()
17 for (
string& s : m_Storage)
20 for (
auto& b : m_FreeMask)
21 b.store(~0ull, std::memory_order_relaxed);
24 constexpr
size_t nRemove = nSize % bTotalBits;
25 if constexpr (nRemove != 0)
27 u64 nValid = (1ull << nRemove) - 1;
28 m_FreeMask[m_FreeMask.size() - 1].store(nValid, std::memory_order_relaxed);
32 template<
size_t nSize>
35 for (
size_t nBlock = 0; nBlock < m_FreeMask.size(); ++nBlock)
37 u64 nMask = m_FreeMask[nBlock].load(std::memory_order_relaxed);
41 const u64 nBit = nMask & (~nMask + 1);
42 const u64 nNewMask = nMask & ~nBit;
44 if (m_FreeMask[nBlock]
45 .compare_exchange_weak(nMask, nNewMask, std::memory_order_acquire, std::memory_order_relaxed))
47 const size_t nIndex = nBlock * bTotalBits + ctz64(nBit);
48 return item { std::move(m_Storage[nIndex]),
static_cast<int>(nIndex) };
57 template<
size_t nSize>
60 if (nIndex == nFreeString)
63 const size_t nSizeIndex =
static_cast<size_t>(nIndex);
64 if (nSizeIndex >= nSize)
70 m_Storage[nSizeIndex] = std::move(sValue);
72 const size_t nBlock = nSizeIndex / bTotalBits;
73 const size_t nOffset = nSizeIndex % bTotalBits;
74 const u64 nBit = 1ull << nOffset;
77 m_FreeMask[nBlock].fetch_or(nBit, std::memory_order_release);
80 template<
size_t nSize>
83 #if QX_GNU || QX_CLANG || QX_APPLE_CLANG
84 return __builtin_ctzll(nBit);
87 while ((nBit & 1) == 0)
96 template<
size_t nSize>
97 void string_pool<nSize>::normalize(
string&
string)
100 string.reserve(bStringStartCapacity);
Fixed-size atomic string pool.
item acquire()
Acquire a string from the pool.
void release(string sValue, int nIndex)
Return a string back to the pool.