From 483eb2f56657e8e7f419ab1a4fab8dce9ade8609 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 27 Apr 2024 20:24:20 +0200 Subject: Adding upstream version 14.2.21. Signed-off-by: Daniel Baumann --- .../libs/histogram/test/utility_allocator.hpp | 131 +++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 src/boost/libs/histogram/test/utility_allocator.hpp (limited to 'src/boost/libs/histogram/test/utility_allocator.hpp') diff --git a/src/boost/libs/histogram/test/utility_allocator.hpp b/src/boost/libs/histogram/test/utility_allocator.hpp new file mode 100644 index 00000000..60745d0e --- /dev/null +++ b/src/boost/libs/histogram/test/utility_allocator.hpp @@ -0,0 +1,131 @@ +// Copyright 2018 Hans Dembinski +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct tracing_allocator_db : std::pair { + template + auto& at() { + return map_[&BOOST_CORE_TYPEID(T)]; + } + + void clear() { + map_.clear(); + this->first = 0; + this->second = 0; + } + + int failure_countdown = -1; + bool tracing = false; + + template + void log(Ts&&... ts) { + if (!tracing) return; + log_impl(std::forward(ts)...); + std::cerr << std::endl; + } + + std::size_t size() const { return map_.size(); } + +private: + using map_t = std::unordered_map>; + map_t map_; + + BOOST_ATTRIBUTE_UNUSED inline void log_impl() {} + + template + void log_impl(T&& t, Ts&&... ts) { + std::cerr << t; + log_impl(std::forward(ts)...); + } +}; + +template +struct tracing_allocator { + using value_type = T; + + tracing_allocator_db* db = nullptr; + + tracing_allocator() noexcept = default; + tracing_allocator(const tracing_allocator&) noexcept = default; + tracing_allocator(tracing_allocator&&) noexcept = default; + + tracing_allocator(tracing_allocator_db& x) noexcept : db(&x) {} + template + tracing_allocator(const tracing_allocator& a) noexcept : db(a.db) {} + template + tracing_allocator& operator=(const tracing_allocator& a) noexcept { + db = a.db; + return *this; + } + ~tracing_allocator() noexcept {} + + T* allocate(std::size_t n) { + if (db) { + if (db->failure_countdown >= 0) { + const auto count = db->failure_countdown--; + db->log("allocator +", n, " ", boost::histogram::detail::type_name(), + " [failure in ", count, "]"); + if (count == 0) BOOST_THROW_EXCEPTION(std::bad_alloc{}); + } else + db->log("allocator +", n, " ", boost::histogram::detail::type_name()); + auto& p = db->at(); + p.first += static_cast(n); + p.second += static_cast(n); + db->first += static_cast(n * sizeof(T)); + db->second += static_cast(n * sizeof(T)); + } + return static_cast(::operator new(n * sizeof(T))); + } + + void deallocate(T* p, std::size_t n) { + if (db) { + db->at().first -= static_cast(n); + db->first -= static_cast(n * sizeof(T)); + db->log("allocator -", n, " ", boost::histogram::detail::type_name()); + } + ::operator delete((void*)p); + } + + template + void construct(T* p, Ts&&... ts) { + if (db) { + if (db->failure_countdown >= 0) { + const auto count = db->failure_countdown--; + db->log("allocator construct ", boost::histogram::detail::type_name(), + "[ failure in ", count, "]"); + if (count == 0) BOOST_THROW_EXCEPTION(std::bad_alloc{}); + } else + db->log("allocator construct ", boost::histogram::detail::type_name()); + } + ::new (static_cast(p)) T(std::forward(ts)...); + } + + void destroy(T* p) { + if (db) db->log("allocator destroy ", boost::histogram::detail::type_name()); + p->~T(); + } +}; + +template +constexpr bool operator==(const tracing_allocator&, + const tracing_allocator&) noexcept { + return true; +} + +template +constexpr bool operator!=(const tracing_allocator& t, + const tracing_allocator& u) noexcept { + return !operator==(t, u); +} -- cgit v1.2.3