From 7ff10c30f17af813fd39eb0a14f7fd5401aba1a9 Mon Sep 17 00:00:00 2001 From: Matthew Parkinson Date: Thu, 19 May 2022 21:19:49 +0100 Subject: [PATCH] Enable accessing parent ranges. (#529) This exposes a feature on Ranges to access ranges higher up the stack of ranges. This could be useful for applying operations in the middle of a pipeline like object_range.ancestor().init(...); This allows some initialisation to be added to the middle of pipeline without breaking the current coding pattern. It also allows for bypassing some ranges object_range.ancestor().alloc_chunk(...); Neither are done in this commit, but both will occur in future commits. Co-authored-by: Nathaniel Wesley Filardo --- src/snmalloc/backend_helpers/commitrange.h | 5 +- src/snmalloc/backend_helpers/globalrange.h | 4 +- .../backend_helpers/largebuddyrange.h | 4 +- src/snmalloc/backend_helpers/logrange.h | 5 +- .../backend_helpers/pagemapregisterrange.h | 7 ++- src/snmalloc/backend_helpers/range_helpers.h | 61 +++++++++++++++++++ .../backend_helpers/smallbuddyrange.h | 4 +- src/snmalloc/backend_helpers/statsrange.h | 5 +- src/snmalloc/backend_helpers/subrange.h | 4 +- 9 files changed, 82 insertions(+), 17 deletions(-) diff --git a/src/snmalloc/backend_helpers/commitrange.h b/src/snmalloc/backend_helpers/commitrange.h index c8d7c61..938c238 100644 --- a/src/snmalloc/backend_helpers/commitrange.h +++ b/src/snmalloc/backend_helpers/commitrange.h @@ -1,13 +1,14 @@ #pragma once #include "../pal/pal.h" #include "empty_range.h" +#include "range_helpers.h" namespace snmalloc { template - class CommitRange + class CommitRange : public ContainsParent { - ParentRange parent{}; + using ContainsParent::parent; public: /** diff --git a/src/snmalloc/backend_helpers/globalrange.h b/src/snmalloc/backend_helpers/globalrange.h index 565b4f3..80f1bca 100644 --- a/src/snmalloc/backend_helpers/globalrange.h +++ b/src/snmalloc/backend_helpers/globalrange.h @@ -10,9 +10,9 @@ namespace snmalloc * and protects access with a lock. */ template - class GlobalRange + class GlobalRange : public StaticParent { - SNMALLOC_REQUIRE_CONSTINIT static inline ParentRange parent{}; + using StaticParent::parent; /** * This is infrequently used code, a spin lock simplifies the code diff --git a/src/snmalloc/backend_helpers/largebuddyrange.h b/src/snmalloc/backend_helpers/largebuddyrange.h index f53fc0b..47e3596 100644 --- a/src/snmalloc/backend_helpers/largebuddyrange.h +++ b/src/snmalloc/backend_helpers/largebuddyrange.h @@ -189,9 +189,9 @@ namespace snmalloc SNMALLOC_CONCEPT(ConceptBuddyRangeMeta) Pagemap, size_t MIN_REFILL_SIZE_BITS = 0, typename ParentRange = EmptyRange> - class LargeBuddyRange + class LargeBuddyRange : public ContainsParent { - ParentRange parent{}; + using ContainsParent::parent; /** * Maximum size of a refill diff --git a/src/snmalloc/backend_helpers/logrange.h b/src/snmalloc/backend_helpers/logrange.h index 8d5ef70..7c53085 100644 --- a/src/snmalloc/backend_helpers/logrange.h +++ b/src/snmalloc/backend_helpers/logrange.h @@ -1,6 +1,7 @@ #pragma once #include "empty_range.h" +#include "range_helpers.h" namespace snmalloc { @@ -11,9 +12,9 @@ namespace snmalloc * ParentRange is what the range is logging calls to. */ template - class LogRange + class LogRange : public ContainsParent { - ParentRange parent{}; + using ContainsParent::parent; public: /** diff --git a/src/snmalloc/backend_helpers/pagemapregisterrange.h b/src/snmalloc/backend_helpers/pagemapregisterrange.h index e75b72f..cd52640 100644 --- a/src/snmalloc/backend_helpers/pagemapregisterrange.h +++ b/src/snmalloc/backend_helpers/pagemapregisterrange.h @@ -2,6 +2,7 @@ #include "../pal/pal.h" #include "empty_range.h" +#include "range_helpers.h" namespace snmalloc { @@ -9,9 +10,9 @@ namespace snmalloc SNMALLOC_CONCEPT(ConceptBackendMetaRange) Pagemap, bool CanConsolidate = true, typename ParentRange = EmptyRange> - class PagemapRegisterRange + class PagemapRegisterRange : public ContainsParent { - ParentRange state{}; + using ContainsParent::parent; public: /** @@ -28,7 +29,7 @@ namespace snmalloc capptr::Chunk alloc_range(size_t size) { - auto base = state.alloc_range(size); + auto base = parent.alloc_range(size); if (base != nullptr) Pagemap::register_range(address_cast(base), size); diff --git a/src/snmalloc/backend_helpers/range_helpers.h b/src/snmalloc/backend_helpers/range_helpers.h index db1a12f..fb7e3e0 100644 --- a/src/snmalloc/backend_helpers/range_helpers.h +++ b/src/snmalloc/backend_helpers/range_helpers.h @@ -69,4 +69,65 @@ namespace snmalloc */ template using Pipe = typename PipeImpl::result; + + /** + * Helper class for allowing a range to be navigated to find an + * ancestor of a specific type. The parent is an instance field. + */ + template + class ContainsParent + { + protected: + Parent parent{}; + + public: + /** + * Returns the outermost Ancestor with the correct type. + * + * Fails to compile if no such ancestor exists. + */ + template + Anc* ancestor() + { + if constexpr (std::is_same_v) + { + return &parent; + } + else + { + return parent.template ancestor(); + } + } + }; + + /** + * Helper class for allowing a range to be navigated to find an + * ancestor of a specific type. The parent is a static field. + */ + template + class StaticParent + { + protected: + SNMALLOC_REQUIRE_CONSTINIT inline static Parent parent{}; + + public: + /** + * Returns the outermost Ancestor with the correct type. + * + * Fails to compile if no such ancestor exists. + */ + template + Anc* ancestor() + { + if constexpr (std::is_same_v) + { + return &parent; + } + else + { + return parent.template ancestor(); + } + } + }; + } // namespace snmalloc diff --git a/src/snmalloc/backend_helpers/smallbuddyrange.h b/src/snmalloc/backend_helpers/smallbuddyrange.h index b199190..780d8cd 100644 --- a/src/snmalloc/backend_helpers/smallbuddyrange.h +++ b/src/snmalloc/backend_helpers/smallbuddyrange.h @@ -144,9 +144,9 @@ namespace snmalloc }; template - class SmallBuddyRange + class SmallBuddyRange : public ContainsParent { - ParentRange parent{}; + using ContainsParent::parent; static constexpr size_t MIN_BITS = bits::next_pow2_bits_const(sizeof(FreeChunk)); diff --git a/src/snmalloc/backend_helpers/statsrange.h b/src/snmalloc/backend_helpers/statsrange.h index 49b18f7..2f6fdbc 100644 --- a/src/snmalloc/backend_helpers/statsrange.h +++ b/src/snmalloc/backend_helpers/statsrange.h @@ -1,6 +1,7 @@ #pragma once #include "empty_range.h" +#include "range_helpers.h" #include @@ -10,9 +11,9 @@ namespace snmalloc * Used to measure memory usage. */ template - class StatsRange + class StatsRange : public ContainsParent { - ParentRange parent{}; + using ContainsParent::parent; static inline std::atomic current_usage{}; static inline std::atomic peak_usage{}; diff --git a/src/snmalloc/backend_helpers/subrange.h b/src/snmalloc/backend_helpers/subrange.h index f345806..ca4f973 100644 --- a/src/snmalloc/backend_helpers/subrange.h +++ b/src/snmalloc/backend_helpers/subrange.h @@ -10,9 +10,9 @@ namespace snmalloc * the end of the large allocation. */ template - class SubRange + class SubRange : public ContainsParent { - ParentRange parent{}; + using ContainsParent::parent; public: /**