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:
committed by
GitHub
parent
888d182bac
commit
87d71cce21
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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");
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user