1 //===------- string_pool.h - Thread-safe pool for strings -------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // Contains a thread-safe string pool. Strings are ref-counted, but not
10 // automatically deallocated. Unused entries can be cleared by calling
11 // StringPool::clearDeadEntries.
13 //===----------------------------------------------------------------------===//
15 #ifndef ORC_RT_STRING_POOL_H
16 #define ORC_RT_STRING_POOL_H
23 #include <unordered_map>
27 class PooledStringPtr
;
29 /// String pool for strings names used by the ORC runtime.
31 friend class PooledStringPtr
;
34 /// Destroy a StringPool.
37 /// Create a string pointer from the given string.
38 PooledStringPtr
intern(std::string S
);
40 /// Remove from the pool any entries that are no longer referenced.
41 void clearDeadEntries();
43 /// Returns true if the pool is empty.
47 using RefCountType
= std::atomic
<size_t>;
48 using PoolMap
= std::unordered_map
<std::string
, RefCountType
>;
49 using PoolMapEntry
= PoolMap::value_type
;
50 mutable std::mutex PoolMutex
;
54 /// Pointer to a pooled string.
55 class PooledStringPtr
{
56 friend class StringPool
;
57 friend struct std::hash
<PooledStringPtr
>;
60 PooledStringPtr() = default;
61 PooledStringPtr(std::nullptr_t
) {}
62 PooledStringPtr(const PooledStringPtr
&Other
) : S(Other
.S
) {
67 PooledStringPtr
&operator=(const PooledStringPtr
&Other
) {
69 assert(S
->second
&& "Releasing PooledStringPtr with zero ref count");
78 PooledStringPtr(PooledStringPtr
&&Other
) : S(nullptr) {
79 std::swap(S
, Other
.S
);
82 PooledStringPtr
&operator=(PooledStringPtr
&&Other
) {
84 assert(S
->second
&& "Releasing PooledStringPtr with zero ref count");
88 std::swap(S
, Other
.S
);
94 assert(S
->second
&& "Releasing PooledStringPtr with zero ref count");
99 explicit operator bool() const { return S
; }
101 const std::string
&operator*() const { return S
->first
; }
103 friend bool operator==(const PooledStringPtr
&LHS
,
104 const PooledStringPtr
&RHS
) {
105 return LHS
.S
== RHS
.S
;
108 friend bool operator!=(const PooledStringPtr
&LHS
,
109 const PooledStringPtr
&RHS
) {
110 return !(LHS
== RHS
);
113 friend bool operator<(const PooledStringPtr
&LHS
,
114 const PooledStringPtr
&RHS
) {
115 return LHS
.S
< RHS
.S
;
119 using PoolEntry
= StringPool::PoolMapEntry
;
120 using PoolEntryPtr
= PoolEntry
*;
122 PooledStringPtr(StringPool::PoolMapEntry
*S
) : S(S
) {
127 PoolEntryPtr S
= nullptr;
130 inline StringPool::~StringPool() {
133 assert(Pool
.empty() && "Dangling references at pool destruction time");
137 inline PooledStringPtr
StringPool::intern(std::string S
) {
138 std::lock_guard
<std::mutex
> Lock(PoolMutex
);
141 std::tie(I
, Added
) = Pool
.try_emplace(std::move(S
), 0);
142 return PooledStringPtr(&*I
);
145 inline void StringPool::clearDeadEntries() {
146 std::lock_guard
<std::mutex
> Lock(PoolMutex
);
147 for (auto I
= Pool
.begin(), E
= Pool
.end(); I
!= E
;) {
149 if (Tmp
->second
== 0)
154 inline bool StringPool::empty() const {
155 std::lock_guard
<std::mutex
> Lock(PoolMutex
);
159 } // end namespace __orc_rt
163 // Make PooledStringPtrs hashable.
164 template <> struct hash
<__orc_rt::PooledStringPtr
> {
165 size_t operator()(const __orc_rt::PooledStringPtr
&A
) const {
166 return hash
<__orc_rt::PooledStringPtr::PoolEntryPtr
>()(A
.S
);
172 #endif // ORC_RT_REF_COUNTED_STRING_POOL_H