
The following patch introduces a new interop interface implementation with the following characteristics: * It supports the new 6.0 prefer_type specification * It supports both explicit objects (from interop constructs) and implicit objects (from variant calls). * Implements a per-thread reuse mechanism for implicit objects to reduce overheads. * It provides a plugin interface that allows selecting the supported interop types, and managing all the backend related interop operations (init, sync, ...). * It enables cooperation with the OpenMP runtime to allow progress on OpenMP synchronizations. * It cleanups some vendor/fr_id mismatchs from the current query routines. * It supports extension to define interop callbacks for library cleanup.
115 lines
3.2 KiB
C++
115 lines
3.2 KiB
C++
//===-- PerThreadTable.h -- PerThread Storage Structure ----*- 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Table indexed with one entry per thread.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef OFFLOAD_PERTHREADTABLE_H
|
|
#define OFFLOAD_PERTHREADTABLE_H
|
|
|
|
#include <list>
|
|
#include <memory>
|
|
#include <mutex>
|
|
|
|
// 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;
|
|
|
|
struct PerThreadData {
|
|
size_t NElements = 0;
|
|
std::unique_ptr<ContainerType> ThEntry;
|
|
};
|
|
|
|
std::mutex Mtx;
|
|
std::list<std::shared_ptr<PerThreadData>> ThreadDataList;
|
|
|
|
// define default constructors, disable copy and move constructors
|
|
PerThreadTable() = default;
|
|
PerThreadTable(const PerThreadTable &) = delete;
|
|
PerThreadTable(PerThreadTable &&) = delete;
|
|
PerThreadTable &operator=(const PerThreadTable &) = delete;
|
|
PerThreadTable &operator=(PerThreadTable &&) = delete;
|
|
~PerThreadTable() {
|
|
std::lock_guard<std::mutex> Lock(Mtx);
|
|
ThreadDataList.clear();
|
|
}
|
|
|
|
private:
|
|
PerThreadData &getThreadData() {
|
|
static thread_local std::shared_ptr<PerThreadData> ThData = nullptr;
|
|
if (!ThData) {
|
|
ThData = std::make_shared<PerThreadData>();
|
|
std::lock_guard<std::mutex> Lock(Mtx);
|
|
ThreadDataList.push_back(ThData);
|
|
}
|
|
return *ThData;
|
|
}
|
|
|
|
protected:
|
|
ContainerType &getThreadEntry() {
|
|
auto &ThData = getThreadData();
|
|
if (ThData.ThEntry)
|
|
return *ThData.ThEntry;
|
|
ThData.ThEntry = std::make_unique<ContainerType>();
|
|
return *ThData.ThEntry;
|
|
}
|
|
|
|
size_t &getThreadNElements() {
|
|
auto &ThData = getThreadData();
|
|
return ThData.NElements;
|
|
}
|
|
|
|
public:
|
|
void add(ObjectType obj) {
|
|
auto &Entry = getThreadEntry();
|
|
auto &NElements = getThreadNElements();
|
|
NElements++;
|
|
Entry.add(obj);
|
|
}
|
|
|
|
iterator erase(iterator it) {
|
|
auto &Entry = getThreadEntry();
|
|
auto &NElements = getThreadNElements();
|
|
NElements--;
|
|
return Entry.erase(it);
|
|
}
|
|
|
|
size_t size() { return getThreadNElements(); }
|
|
|
|
// Iterators to traverse objects owned by
|
|
// the current thread
|
|
iterator begin() {
|
|
auto &Entry = getThreadEntry();
|
|
return Entry.begin();
|
|
}
|
|
iterator end() {
|
|
auto &Entry = getThreadEntry();
|
|
return Entry.end();
|
|
}
|
|
|
|
template <class F> void clear(F f) {
|
|
std::lock_guard<std::mutex> Lock(Mtx);
|
|
for (auto ThData : ThreadDataList) {
|
|
if (!ThData->ThEntry || ThData->NElements == 0)
|
|
continue;
|
|
ThData->ThEntry->clear(f);
|
|
ThData->NElements = 0;
|
|
}
|
|
ThreadDataList.clear();
|
|
}
|
|
};
|
|
|
|
#endif
|