13 template<
size_t nSize,
size_t bStringStartCapacity>
14 string_pool<nSize, bStringStartCapacity>::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,
size_t bStringStartCapacity>
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,
size_t bStringStartCapacity>
60 if (
item.nIndex == nFreeString)
63 const size_t nSizeIndex =
static_cast<size_t>(
item.nIndex);
64 if (nSizeIndex >= nSize)
67 normalize(
item.sValue);
70 m_Storage[nSizeIndex] = std::move(
item.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,
size_t bStringStartCapacity>
83 #if QX_GNU || QX_CLANG || QX_APPLE_CLANG
84 return __builtin_ctzll(nBit);
87 while ((nBit & 1) == 0)
96 template<
size_t nSize,
size_t bStringStartCapacity>
97 void string_pool<nSize, bStringStartCapacity>::normalize(
string&
string)
100 string.reserve(bStringStartCapacity);
Fixed-size atomic string pool.
item acquire()
Acquire a string from the pool.
void release(item item)
Return a string back to the pool.