Skip to content

Commit

Permalink
Add indirect range (#562)
Browse files Browse the repository at this point in the history
* Add indirect range

The ranges currently either completely own the parent range, or it is
a static and thus completely shared.

The indirect range allows sharing without it being global.

Co-authored-by: Nathaniel Filardo <nfilardo@microsoft.com>
  • Loading branch information
mjp41 and nwf-msr authored Sep 21, 2022
1 parent fb85216 commit 591dc4c
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/snmalloc/backend_helpers/backend_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "defaultpagemapentry.h"
#include "empty_range.h"
#include "globalrange.h"
#include "indirectrange.h"
#include "largebuddyrange.h"
#include "logrange.h"
#include "pagemap.h"
Expand Down
54 changes: 54 additions & 0 deletions src/snmalloc/backend_helpers/indirectrange.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#pragma once

#include "../ds/ds.h"
#include "empty_range.h"

namespace snmalloc
{
/**
* Stores a references to the parent range so that it can be shared
* without `static` scope.
*
* This could be used to allow multiple allocators on a single region of
* memory.
*/
struct IndirectRange
{
template<typename ParentRange = EmptyRange<>>
class Type : public RefParent<ParentRange>
{
using RefParent<ParentRange>::parent;

public:
static constexpr bool Aligned = ParentRange::Aligned;

static_assert(
ParentRange::ConcurrencySafe,
"IndirectRange requires a concurrency safe parent.");

static constexpr bool ConcurrencySafe = true;

using ChunkBounds = typename ParentRange::ChunkBounds;

constexpr Type() = default;

CapPtr<void, ChunkBounds> alloc_range(size_t size)
{
return parent->alloc_range(size);
}

void dealloc_range(CapPtr<void, ChunkBounds> base, size_t size)
{
parent->dealloc_range(base, size);
}

/**
* Points the parent reference to the given range.
*/
void set_parent(ParentRange* p)
{
parent = p;
}
};
};
} // namespace snmalloc
31 changes: 31 additions & 0 deletions src/snmalloc/backend_helpers/range_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,4 +130,35 @@ namespace snmalloc
}
};

/**
* Helper class for allowing a range to be navigated to find an
* ancestor of a specific type. The parent is a pointer to a range;
* this allows the parent to be shared.
*/
template<typename Parent>
class RefParent
{
protected:
Parent* parent{};

public:
/**
* Returns the outermost Ancestor with the correct type.
*
* Fails to compile if no such ancestor exists.
*/
template<typename Anc>
Anc* ancestor()
{
if constexpr (std::is_same_v<Anc, Parent>)
{
return parent;
}
else
{
return parent->template ancestor<Anc>();
}
}
};

} // namespace snmalloc

0 comments on commit 591dc4c

Please sign in to comment.