107 lines
3.2 KiB
C++
107 lines
3.2 KiB
C++
/*
|
|
* Copyright (C) 2018-2024 Intel Corporation
|
|
*
|
|
* SPDX-License-Identifier: MIT
|
|
*
|
|
*/
|
|
|
|
#pragma once
|
|
#include "shared/source/helpers/debug_helpers.h"
|
|
|
|
#include <algorithm>
|
|
#include <limits>
|
|
#include <memory>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
namespace NEO {
|
|
|
|
template <typename ValueType>
|
|
class BaseSortedPointerWithValueVector {
|
|
public:
|
|
using PointerPair = std::pair<const void *, std::unique_ptr<ValueType>>;
|
|
using Container = std::vector<PointerPair>;
|
|
|
|
BaseSortedPointerWithValueVector() = default;
|
|
|
|
bool comparePointers(size_t allowedOffset, const void *ptr, const void *otherPtr) {
|
|
return ptr == otherPtr || (allowedOffset > 0u && (otherPtr < ptr &&
|
|
(reinterpret_cast<uintptr_t>(ptr) < (reinterpret_cast<uintptr_t>(otherPtr) + allowedOffset))));
|
|
}
|
|
|
|
size_t getAllocationSize(const std::unique_ptr<ValueType> &data) {
|
|
return data->size;
|
|
}
|
|
|
|
void insert(const void *ptr, const ValueType &value) {
|
|
allocations.push_back(std::make_pair(ptr, std::make_unique<ValueType>(value)));
|
|
for (size_t i = allocations.size() - 1; i > 0; --i) {
|
|
if (allocations[i].first < allocations[i - 1].first) {
|
|
std::iter_swap(allocations.begin() + i, allocations.begin() + i - 1);
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void remove(const void *ptr) {
|
|
auto removeIt = std::remove_if(allocations.begin(), allocations.end(), [&ptr](const PointerPair &other) {
|
|
return ptr == other.first;
|
|
});
|
|
allocations.erase(removeIt);
|
|
}
|
|
|
|
typename Container::iterator getImpl(const void *ptr, bool allowOffset) {
|
|
if (allocations.size() == 0) {
|
|
return allocations.end();
|
|
}
|
|
|
|
if (nullptr == ptr) {
|
|
return allocations.end();
|
|
}
|
|
|
|
DEBUG_BREAK_IF(allocations.size() > static_cast<size_t>(std::numeric_limits<int>::max()));
|
|
|
|
int begin = 0;
|
|
int end = static_cast<int>(allocations.size() - 1);
|
|
while (end >= begin) {
|
|
int currentPos = (begin + end) / 2;
|
|
const auto &allocation = allocations[currentPos];
|
|
const size_t allowedOffset = allowOffset ? getAllocationSize(allocation.second) : 0u;
|
|
if (comparePointers(allowedOffset, ptr, allocation.first)) {
|
|
return allocations.begin() + currentPos;
|
|
} else if (ptr < allocation.first) {
|
|
end = currentPos - 1;
|
|
continue;
|
|
} else {
|
|
begin = currentPos + 1;
|
|
continue;
|
|
}
|
|
}
|
|
return allocations.end();
|
|
}
|
|
|
|
std::unique_ptr<ValueType> extract(const void *ptr) {
|
|
std::unique_ptr<ValueType> retVal{};
|
|
auto it = getImpl(ptr, false);
|
|
if (it != allocations.end()) {
|
|
retVal.swap(it->second);
|
|
allocations.erase(it);
|
|
}
|
|
return retVal;
|
|
}
|
|
|
|
ValueType *get(const void *ptr) {
|
|
auto it = getImpl(ptr, true);
|
|
if (it != allocations.end()) {
|
|
return it->second.get();
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
size_t getNumAllocs() const { return allocations.size(); }
|
|
|
|
Container allocations;
|
|
};
|
|
} // namespace NEO
|