/* * Copyright (C) 2018-2024 Intel Corporation * * SPDX-License-Identifier: MIT * */ #pragma once #include "shared/source/helpers/debug_helpers.h" #include #include #include #include #include namespace NEO { template class BaseSortedPointerWithValueVector { public: using PointerPair = std::pair>; using Container = std::vector; BaseSortedPointerWithValueVector() = default; bool comparePointers(size_t allowedOffset, const void *ptr, const void *otherPtr) { return ptr == otherPtr || (allowedOffset > 0u && (otherPtr < ptr && (reinterpret_cast(ptr) < (reinterpret_cast(otherPtr) + allowedOffset)))); } size_t getAllocationSize(const std::unique_ptr &data) { return data->size; } void insert(const void *ptr, const ValueType &value) { allocations.push_back(std::make_pair(ptr, std::make_unique(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(std::numeric_limits::max())); int begin = 0; int end = static_cast(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 extract(const void *ptr) { std::unique_ptr 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