Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add indirect range #562

Merged
merged 5 commits into from
Sep 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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