[llvm] [OFFLOAD] Add support for indexed per-thread containers (PR #164263)
Kevin Sala Penades via llvm-commits
llvm-commits at lists.llvm.org
Thu Nov 20 14:52:10 PST 2025
================
@@ -14,26 +14,106 @@
#define OFFLOAD_PERTHREADTABLE_H
#include <list>
+#include <llvm/ADT/SmallVector.h>
+#include <llvm/Support/Error.h>
#include <memory>
#include <mutex>
+#include <type_traits>
+
+template <typename ObjectType> struct PerThread {
+ struct PerThreadData {
+ std::unique_ptr<ObjectType> ThreadEntry;
+ };
+
+ std::mutex Mutex;
+ llvm::SmallVector<std::shared_ptr<PerThreadData>> ThreadDataList;
+
+ // define default constructors, disable copy and move constructors
+ PerThread() = default;
+ PerThread(const PerThread &) = delete;
+ PerThread(PerThread &&) = delete;
+ PerThread &operator=(const PerThread &) = delete;
+ PerThread &operator=(PerThread &&) = delete;
+ ~PerThread() {
+ assert(Mutex.try_lock() && (Mutex.unlock(), true) &&
+ "Cannot be deleted while other threads are adding entries");
+ ThreadDataList.clear();
+ }
+
+private:
+ PerThreadData &getThreadData() {
+ static thread_local std::shared_ptr<PerThreadData> ThreadData = nullptr;
+ if (!ThreadData) {
+ ThreadData = std::make_shared<PerThreadData>();
+ std::lock_guard<std::mutex> Lock(Mutex);
+ ThreadDataList.push_back(ThreadData);
+ }
+ return *ThreadData;
+ }
+
+protected:
+ ObjectType &getThreadEntry() {
+ PerThreadData &ThreadData = getThreadData();
+ if (ThreadData.ThreadEntry)
+ return *ThreadData.ThreadEntry;
+ ThreadData.ThreadEntry = std::make_unique<ObjectType>();
+ return *ThreadData.ThreadEntry;
+ }
+
+public:
+ ObjectType &get() { return getThreadEntry(); }
+
+ template <class ClearFuncTy> void clear(ClearFuncTy ClearFunc) {
+ assert(Mutex.try_lock() && (Mutex.unlock(), true) &&
+ "Clear cannot be called while other threads are adding entries");
+ for (std::shared_ptr<PerThreadData> ThreadData : ThreadDataList) {
+ if (!ThreadData->ThreadEntry)
+ continue;
+ ClearFunc(*ThreadData->ThreadEntry);
+ }
+ ThreadDataList.clear();
+ }
+};
// Using an STL container (such as std::vector) indexed by thread ID has
// too many race conditions issues so we store each thread entry into a
// thread_local variable.
// T is the container type used to store the objects, e.g., std::vector,
// std::set, etc. by each thread. O is the type of the stored objects e.g.,
// omp_interop_val_t *, ...
-
template <typename ContainerType, typename ObjectType> struct PerThreadTable {
using iterator = typename ContainerType::iterator;
+ template <typename, typename = std::void_t<>>
+ struct has_iterator : std::false_type {};
+ template <typename T>
+ struct has_iterator<T, std::void_t<typename T::iterator>> : std::true_type {};
+
+ template <typename T, typename = std::void_t<>>
+ struct has_clear : std::false_type {};
+ template <typename T>
+ struct has_clear<T, std::void_t<decltype(std::declval<T>().clear())>>
+ : std::true_type {};
+
+ template <typename T, typename = std::void_t<>>
+ struct has_clearAll : std::false_type {};
+ template <typename T>
+ struct has_clearAll<T, std::void_t<decltype(std::declval<T>().clearAll(1))>>
+ : std::true_type {};
+
+ template <typename, typename = std::void_t<>>
+ struct is_associative : std::false_type {};
+ template <typename T>
+ struct is_associative<T, std::void_t<typename T::mapped_type>>
+ : std::true_type {};
+
struct PerThreadData {
size_t NElements = 0;
----------------
kevinsala wrote:
Okay. Can we rename it to `Size`?
https://github.com/llvm/llvm-project/pull/164263
More information about the llvm-commits
mailing list