aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/compiler-rt/lib/orc/string_pool.h
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/compiler-rt/lib/orc/string_pool.h')
-rw-r--r--contrib/llvm-project/compiler-rt/lib/orc/string_pool.h172
1 files changed, 172 insertions, 0 deletions
diff --git a/contrib/llvm-project/compiler-rt/lib/orc/string_pool.h b/contrib/llvm-project/compiler-rt/lib/orc/string_pool.h
new file mode 100644
index 000000000000..c0ba4ea8980e
--- /dev/null
+++ b/contrib/llvm-project/compiler-rt/lib/orc/string_pool.h
@@ -0,0 +1,172 @@
+//===------- string_pool.h - Thread-safe pool for strings -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Contains a thread-safe string pool. Strings are ref-counted, but not
+// automatically deallocated. Unused entries can be cleared by calling
+// StringPool::clearDeadEntries.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef ORC_RT_STRING_POOL_H
+#define ORC_RT_STRING_POOL_H
+
+#include <atomic>
+#include <cassert>
+#include <functional>
+#include <mutex>
+#include <string>
+#include <unordered_map>
+
+namespace __orc_rt {
+
+class PooledStringPtr;
+
+/// String pool for strings names used by the ORC runtime.
+class StringPool {
+ friend class PooledStringPtr;
+
+public:
+ /// Destroy a StringPool.
+ ~StringPool();
+
+ /// Create a string pointer from the given string.
+ PooledStringPtr intern(std::string S);
+
+ /// Remove from the pool any entries that are no longer referenced.
+ void clearDeadEntries();
+
+ /// Returns true if the pool is empty.
+ bool empty() const;
+
+private:
+ using RefCountType = std::atomic<size_t>;
+ using PoolMap = std::unordered_map<std::string, RefCountType>;
+ using PoolMapEntry = PoolMap::value_type;
+ mutable std::mutex PoolMutex;
+ PoolMap Pool;
+};
+
+/// Pointer to a pooled string.
+class PooledStringPtr {
+ friend class StringPool;
+ friend struct std::hash<PooledStringPtr>;
+
+public:
+ PooledStringPtr() = default;
+ PooledStringPtr(std::nullptr_t) {}
+ PooledStringPtr(const PooledStringPtr &Other) : S(Other.S) {
+ if (S)
+ ++S->second;
+ }
+
+ PooledStringPtr &operator=(const PooledStringPtr &Other) {
+ if (S) {
+ assert(S->second && "Releasing PooledStringPtr with zero ref count");
+ --S->second;
+ }
+ S = Other.S;
+ if (S)
+ ++S->second;
+ return *this;
+ }
+
+ PooledStringPtr(PooledStringPtr &&Other) : S(nullptr) {
+ std::swap(S, Other.S);
+ }
+
+ PooledStringPtr &operator=(PooledStringPtr &&Other) {
+ if (S) {
+ assert(S->second && "Releasing PooledStringPtr with zero ref count");
+ --S->second;
+ }
+ S = nullptr;
+ std::swap(S, Other.S);
+ return *this;
+ }
+
+ ~PooledStringPtr() {
+ if (S) {
+ assert(S->second && "Releasing PooledStringPtr with zero ref count");
+ --S->second;
+ }
+ }
+
+ explicit operator bool() const { return S; }
+
+ const std::string &operator*() const { return S->first; }
+
+ friend bool operator==(const PooledStringPtr &LHS,
+ const PooledStringPtr &RHS) {
+ return LHS.S == RHS.S;
+ }
+
+ friend bool operator!=(const PooledStringPtr &LHS,
+ const PooledStringPtr &RHS) {
+ return !(LHS == RHS);
+ }
+
+ friend bool operator<(const PooledStringPtr &LHS,
+ const PooledStringPtr &RHS) {
+ return LHS.S < RHS.S;
+ }
+
+private:
+ using PoolEntry = StringPool::PoolMapEntry;
+ using PoolEntryPtr = PoolEntry *;
+
+ PooledStringPtr(StringPool::PoolMapEntry *S) : S(S) {
+ if (S)
+ ++S->second;
+ }
+
+ PoolEntryPtr S = nullptr;
+};
+
+inline StringPool::~StringPool() {
+#ifndef NDEBUG
+ clearDeadEntries();
+ assert(Pool.empty() && "Dangling references at pool destruction time");
+#endif // NDEBUG
+}
+
+inline PooledStringPtr StringPool::intern(std::string S) {
+ std::lock_guard<std::mutex> Lock(PoolMutex);
+ PoolMap::iterator I;
+ bool Added;
+ std::tie(I, Added) = Pool.try_emplace(std::move(S), 0);
+ return PooledStringPtr(&*I);
+}
+
+inline void StringPool::clearDeadEntries() {
+ std::lock_guard<std::mutex> Lock(PoolMutex);
+ for (auto I = Pool.begin(), E = Pool.end(); I != E;) {
+ auto Tmp = I++;
+ if (Tmp->second == 0)
+ Pool.erase(Tmp);
+ }
+}
+
+inline bool StringPool::empty() const {
+ std::lock_guard<std::mutex> Lock(PoolMutex);
+ return Pool.empty();
+}
+
+} // end namespace __orc_rt
+
+namespace std {
+
+// Make PooledStringPtrs hashable.
+template <> struct hash<__orc_rt::PooledStringPtr> {
+ size_t operator()(const __orc_rt::PooledStringPtr &A) const {
+ return hash<__orc_rt::PooledStringPtr::PoolEntryPtr>()(A.S);
+ }
+};
+
+} // namespace std
+
+#endif // ORC_RT_REF_COUNTED_STRING_POOL_H