Add a pipe operation to ranges (#527)

The ranges are naturally put together with pipes. This
commit does some template magic to make the code more
readable.  There should be now functional changes with
this change.
This commit is contained in:
Matthew Parkinson
2022-05-17 16:34:00 +01:00
committed by GitHub
parent 888d182bac
commit 87d71cce21
10 changed files with 146 additions and 42 deletions

View File

@@ -98,11 +98,12 @@ namespace snmalloc
#endif
// Set up source of memory
using P = PalRange<PAL>;
using Base = std::conditional_t<
fixed_range,
EmptyRange,
PagemapRegisterRange<Pagemap, P, CONSOLIDATE_PAL_ALLOCS>>;
Pipe<
PalRange<Pal>,
PagemapRegisterRange<Pagemap, CONSOLIDATE_PAL_ALLOCS>>>;
static constexpr size_t MinBaseSizeBits()
{
@@ -117,50 +118,56 @@ namespace snmalloc
}
// Global range of memory
using GlobalR = GlobalRange<LogRange<
2,
LargeBuddyRange<Base, 24, bits::BITS - 1, Pagemap, MinBaseSizeBits()>>>;
using GlobalR = Pipe<
Base,
LargeBuddyRange<24, bits::BITS - 1, Pagemap, MinBaseSizeBits()>,
LogRange<2>,
GlobalRange<>>;
#ifdef SNMALLOC_META_PROTECTED
// Introduce two global ranges, so we don't mix Object and Meta
using CentralObjectRange = GlobalRange<LogRange<
3,
LargeBuddyRange<
GlobalR,
24,
bits::BITS - 1,
Pagemap,
MinBaseSizeBits()>>>;
using CentralMetaRange = GlobalRange<LogRange<
4,
LargeBuddyRange<
SubRange<GlobalR, PAL, 6>, // Use SubRange to introduce guard pages.
24,
bits::BITS - 1,
Pagemap,
MinBaseSizeBits()>>>;
using CentralObjectRange = Pipe<
GlobalR,
LargeBuddyRange<24, bits::BITS - 1, Pagemap, MinBaseSizeBits()>,
LogRange<3>,
GlobalRange<>>;
using CentralMetaRange = Pipe<
GlobalR,
SubRange<PAL, 6>, // Use SubRange to introduce guard pages.
LargeBuddyRange<24, bits::BITS - 1, Pagemap, MinBaseSizeBits()>,
LogRange<4>,
GlobalRange<>>;
// Source for object allocations
using StatsObject = StatsRange<CommitRange<CentralObjectRange, PAL>>;
using StatsObject =
Pipe<CentralObjectRange, CommitRange<PAL>, StatsRange<>>;
using ObjectRange =
LogRange<5, LargeBuddyRange<StatsObject, 21, 21, Pagemap>>;
Pipe<StatsObject, LargeBuddyRange<21, 21, Pagemap>, LogRange<5>>;
using StatsMeta = StatsRange<CommitRange<CentralMetaRange, PAL>>;
using StatsMeta = Pipe<CentralMetaRange, CommitRange<PAL>, StatsRange<>>;
using MetaRange = Pipe<
StatsMeta,
LargeBuddyRange<21 - 6, bits::BITS - 1, Pagemap>,
SmallBuddyRange<>>;
using MetaRange = SmallBuddyRange<
LargeBuddyRange<StatsMeta, 21 - 6, bits::BITS - 1, Pagemap>>;
// Create global range that can service small meta-data requests.
// Don't want to add this to the CentralMetaRange to move Commit outside the
// lock on the common case.
using GlobalMetaRange = GlobalRange<SmallBuddyRange<StatsMeta>>;
using GlobalMetaRange = Pipe<StatsMeta, SmallBuddyRange<>, GlobalRange<>>;
using Stats = StatsCombiner<StatsObject, StatsMeta>;
#else
// Source for object allocations and metadata
// No separation between the two
using Stats = StatsRange<GlobalR>;
using ObjectRange = SmallBuddyRange<
LargeBuddyRange<CommitRange<Stats, PAL>, 21, 21, Pagemap>>;
using GlobalMetaRange = GlobalRange<ObjectRange>;
using Stats = Pipe<GlobalR, StatsRange<>>;
using ObjectRange = Pipe<
Stats,
CommitRange<PAL>,
LargeBuddyRange<21, 21, Pagemap>,
SmallBuddyRange<>>;
using GlobalMetaRange = Pipe<ObjectRange, GlobalRange<>>;
#endif
struct LocalState

View File

@@ -1,15 +1,21 @@
#pragma once
#include "../pal/pal.h"
#include "empty_range.h"
namespace snmalloc
{
template<typename ParentRange, typename PAL>
template<typename PAL, typename ParentRange = EmptyRange>
class CommitRange
{
ParentRange parent{};
public:
/**
* We use a nested Apply type to enable a Pipe operation.
*/
template<typename ParentRange2>
using Apply = CommitRange<PAL, ParentRange2>;
static constexpr bool Aligned = ParentRange::Aligned;
static constexpr bool ConcurrencySafe = ParentRange::ConcurrencySafe;

View File

@@ -1,6 +1,7 @@
#pragma once
#include "../ds/ds.h"
#include "empty_range.h"
namespace snmalloc
{
@@ -8,7 +9,7 @@ namespace snmalloc
* Makes the supplied ParentRange into a global variable,
* and protects access with a lock.
*/
template<typename ParentRange>
template<typename ParentRange = EmptyRange>
class GlobalRange
{
SNMALLOC_REQUIRE_CONSTINIT static inline ParentRange parent{};
@@ -20,6 +21,12 @@ namespace snmalloc
SNMALLOC_REQUIRE_CONSTINIT static inline FlagWord spin_lock{};
public:
/**
* We use a nested Apply type to enable a Pipe operation.
*/
template<typename ParentRange2>
using Apply = GlobalRange<ParentRange2>;
static constexpr bool Aligned = ParentRange::Aligned;
static constexpr bool ConcurrencySafe = true;

View File

@@ -3,6 +3,7 @@
#include "../ds/ds.h"
#include "../mem/mem.h"
#include "buddy.h"
#include "empty_range.h"
#include "range_helpers.h"
#include <string>
@@ -183,11 +184,11 @@ namespace snmalloc
* for
*/
template<
typename ParentRange,
size_t REFILL_SIZE_BITS,
size_t MAX_SIZE_BITS,
SNMALLOC_CONCEPT(ConceptBuddyRangeMeta) Pagemap,
size_t MIN_REFILL_SIZE_BITS = 0>
size_t MIN_REFILL_SIZE_BITS = 0,
typename ParentRange = EmptyRange>
class LargeBuddyRange
{
ParentRange parent{};
@@ -327,6 +328,17 @@ namespace snmalloc
}
public:
/**
* We use a nested Apply type to enable a Pipe operation.
*/
template<typename ParentRange2>
using Apply = LargeBuddyRange<
REFILL_SIZE_BITS,
MAX_SIZE_BITS,
Pagemap,
MIN_REFILL_SIZE_BITS,
ParentRange2>;
static constexpr bool Aligned = true;
static constexpr bool ConcurrencySafe = false;

View File

@@ -1,5 +1,7 @@
#pragma once
#include "empty_range.h"
namespace snmalloc
{
/**
@@ -8,12 +10,18 @@ namespace snmalloc
*
* ParentRange is what the range is logging calls to.
*/
template<size_t RangeName, typename ParentRange>
template<size_t RangeName, typename ParentRange = EmptyRange>
class LogRange
{
ParentRange parent{};
public:
/**
* We use a nested Apply type to enable a Pipe operation.
*/
template<typename ParentRange2>
using Apply = LogRange<RangeName, ParentRange2>;
static constexpr bool Aligned = ParentRange::Aligned;
static constexpr bool ConcurrencySafe = ParentRange::ConcurrencySafe;

View File

@@ -1,18 +1,25 @@
#pragma once
#include "../pal/pal.h"
#include "empty_range.h"
namespace snmalloc
{
template<
SNMALLOC_CONCEPT(ConceptBackendMetaRange) Pagemap,
typename ParentRange,
bool CanConsolidate = true>
bool CanConsolidate = true,
typename ParentRange = EmptyRange>
class PagemapRegisterRange
{
ParentRange state{};
public:
/**
* We use a nested Apply type to enable a Pipe operation.
*/
template<typename ParentRange2>
using Apply = PagemapRegisterRange<Pagemap, CanConsolidate, ParentRange2>;
constexpr PagemapRegisterRange() = default;
static constexpr bool Aligned = ParentRange::Aligned;

View File

@@ -34,4 +34,39 @@ namespace snmalloc
length -= align;
}
}
/**
* Forward definition to allow multiple template specialisations.
*
* This struct is used to recursively compose ranges.
*/
template<typename... Args>
struct PipeImpl;
/**
* Base case of one range that needs nothing.
*/
template<typename Only>
struct PipeImpl<Only>
{
using result = Only;
};
/**
* Recursive case of applying a base range as an argument to the
* next, and then using that as the new base range.
*/
template<typename First, typename Fun, typename... Rest>
struct PipeImpl<First, Fun, Rest...>
{
public:
using result =
typename PipeImpl<typename Fun::template Apply<First>, Rest...>::result;
};
/**
* Nice type so the caller doesn't need to call result explicitly.
*/
template<typename... Args>
using Pipe = typename PipeImpl<Args...>::result;
} // namespace snmalloc

View File

@@ -1,6 +1,7 @@
#pragma once
#include "../pal/pal.h"
#include "empty_range.h"
#include "range_helpers.h"
namespace snmalloc
@@ -142,7 +143,7 @@ namespace snmalloc
}
};
template<typename ParentRange>
template<typename ParentRange = EmptyRange>
class SmallBuddyRange
{
ParentRange parent{};
@@ -179,6 +180,12 @@ namespace snmalloc
}
public:
/**
* We use a nested Apply type to enable a Pipe operation.
*/
template<typename ParentRange2>
using Apply = SmallBuddyRange<ParentRange2>;
static constexpr bool Aligned = true;
static_assert(ParentRange::Aligned, "ParentRange must be aligned");

View File

@@ -1,5 +1,7 @@
#pragma once
#include "empty_range.h"
#include <atomic>
namespace snmalloc
@@ -7,7 +9,7 @@ namespace snmalloc
/**
* Used to measure memory usage.
*/
template<typename ParentRange>
template<typename ParentRange = EmptyRange>
class StatsRange
{
ParentRange parent{};
@@ -16,6 +18,12 @@ namespace snmalloc
static inline std::atomic<size_t> peak_usage{};
public:
/**
* We use a nested Apply type to enable a Pipe operation.
*/
template<typename ParentRange2>
using Apply = StatsRange<ParentRange2>;
static constexpr bool Aligned = ParentRange::Aligned;
static constexpr bool ConcurrencySafe = ParentRange::ConcurrencySafe;

View File

@@ -1,5 +1,6 @@
#pragma once
#include "../mem/mem.h"
#include "empty_range.h"
namespace snmalloc
{
@@ -8,12 +9,18 @@ namespace snmalloc
* 2^RATIO_BITS. Will not return a the block at the start or
* the end of the large allocation.
*/
template<typename ParentRange, typename PAL, size_t RATIO_BITS>
template<typename PAL, size_t RATIO_BITS, typename ParentRange = EmptyRange>
class SubRange
{
ParentRange parent{};
public:
/**
* We use a nested Apply type to enable a Pipe operation.
*/
template<typename ParentRange2>
using Apply = SubRange<PAL, RATIO_BITS, ParentRange2>;
constexpr SubRange() = default;
static constexpr bool Aligned = ParentRange::Aligned;