1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
|
//===- SymbolStringPool.h - Multi-threaded pool for JIT symbols -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Contains a multi-threaded string pool suitable for use with ORC.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_EXECUTIONENGINE_ORC_SYMBOLSTRINGPOOL_H
#define LLVM_EXECUTIONENGINE_ORC_SYMBOLSTRINGPOOL_H
#include "llvm/ADT/StringMap.h"
#include <atomic>
#include <mutex>
namespace llvm {
namespace orc {
class SymbolStringPtr;
/// String pool for symbol names used by the JIT.
class SymbolStringPool {
friend class SymbolStringPtr;
public:
/// Destroy a SymbolStringPool.
~SymbolStringPool();
/// Create a symbol string pointer from the given string.
SymbolStringPtr intern(StringRef 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 = StringMap<RefCountType>;
using PoolMapEntry = StringMapEntry<RefCountType>;
mutable std::mutex PoolMutex;
PoolMap Pool;
};
/// Pointer to a pooled string representing a symbol name.
class SymbolStringPtr {
friend class SymbolStringPool;
friend bool operator==(const SymbolStringPtr &LHS,
const SymbolStringPtr &RHS);
friend bool operator<(const SymbolStringPtr &LHS, const SymbolStringPtr &RHS);
public:
SymbolStringPtr() = default;
SymbolStringPtr(const SymbolStringPtr &Other)
: S(Other.S) {
if (S)
++S->getValue();
}
SymbolStringPtr& operator=(const SymbolStringPtr &Other) {
if (S)
--S->getValue();
S = Other.S;
if (S)
++S->getValue();
return *this;
}
SymbolStringPtr(SymbolStringPtr &&Other) : S(nullptr) {
std::swap(S, Other.S);
}
SymbolStringPtr& operator=(SymbolStringPtr &&Other) {
if (S)
--S->getValue();
S = nullptr;
std::swap(S, Other.S);
return *this;
}
~SymbolStringPtr() {
if (S)
--S->getValue();
}
StringRef operator*() const { return S->first(); }
private:
SymbolStringPtr(SymbolStringPool::PoolMapEntry *S)
: S(S) {
if (S)
++S->getValue();
}
SymbolStringPool::PoolMapEntry *S = nullptr;
};
inline bool operator==(const SymbolStringPtr &LHS, const SymbolStringPtr &RHS) {
return LHS.S == RHS.S;
}
inline bool operator!=(const SymbolStringPtr &LHS, const SymbolStringPtr &RHS) {
return !(LHS == RHS);
}
inline bool operator<(const SymbolStringPtr &LHS, const SymbolStringPtr &RHS) {
return LHS.S < RHS.S;
}
inline SymbolStringPool::~SymbolStringPool() {
#ifndef NDEBUG
clearDeadEntries();
assert(Pool.empty() && "Dangling references at pool destruction time");
#endif // NDEBUG
}
inline SymbolStringPtr SymbolStringPool::intern(StringRef S) {
std::lock_guard<std::mutex> Lock(PoolMutex);
PoolMap::iterator I;
bool Added;
std::tie(I, Added) = Pool.try_emplace(S, 0);
return SymbolStringPtr(&*I);
}
inline void SymbolStringPool::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 SymbolStringPool::empty() const {
std::lock_guard<std::mutex> Lock(PoolMutex);
return Pool.empty();
}
} // end namespace orc
} // end namespace llvm
#endif // LLVM_EXECUTIONENGINE_ORC_SYMBOLSTRINGPOOL_H
|