Separate locking from static range (#540)

Pull a part the locking from the static range. This enables
locking to be added to a range directly, and does not require
it to be made static.  This is useful in cases where the source
of memory is shared between threads, but not static.  I.e. there
are multiple instances of the same type.
This commit is contained in:
Matthew Parkinson
2022-09-08 10:40:04 +01:00
committed by GitHub
parent 8f8dbd83b5
commit a118c9b7d8
3 changed files with 92 additions and 31 deletions

View File

@@ -2,6 +2,8 @@
#include "../ds/ds.h"
#include "empty_range.h"
#include "lockrange.h"
#include "staticrange.h"
namespace snmalloc
{
@@ -12,36 +14,7 @@ namespace snmalloc
struct GlobalRange
{
template<typename ParentRange = EmptyRange<>>
class Type : public StaticParent<ParentRange>
{
using StaticParent<ParentRange>::parent;
/**
* This is infrequently used code, a spin lock simplifies the code
* considerably, and should never be on the fast path.
*/
SNMALLOC_REQUIRE_CONSTINIT static inline FlagWord spin_lock{};
public:
static constexpr bool Aligned = ParentRange::Aligned;
static constexpr bool ConcurrencySafe = true;
using ChunkBounds = typename ParentRange::ChunkBounds;
constexpr Type() = default;
CapPtr<void, ChunkBounds> alloc_range(size_t size)
{
FlagLock lock(spin_lock);
return parent.alloc_range(size);
}
void dealloc_range(CapPtr<void, ChunkBounds> base, size_t size)
{
FlagLock lock(spin_lock);
parent.dealloc_range(base, size);
}
};
class Type : public Pipe<ParentRange, LockRange, StaticRange>
{};
};
} // namespace snmalloc

View File

@@ -0,0 +1,46 @@
#pragma once
#include "../ds/ds.h"
#include "empty_range.h"
namespace snmalloc
{
/**
* Protect the ParentRange with a spin lock.
*/
struct LockRange
{
template<typename ParentRange = EmptyRange<>>
class Type : public ContainsParent<ParentRange>
{
using ContainsParent<ParentRange>::parent;
/**
* This is infrequently used code, a spin lock simplifies the code
* considerably, and should never be on the fast path.
*/
FlagWord spin_lock{};
public:
static constexpr bool Aligned = ParentRange::Aligned;
using ChunkBounds = typename ParentRange::ChunkBounds;
static constexpr bool ConcurrencySafe = true;
constexpr Type() = default;
CapPtr<void, ChunkBounds> alloc_range(size_t size)
{
FlagLock lock(spin_lock);
return parent.alloc_range(size);
}
void dealloc_range(CapPtr<void, ChunkBounds> base, size_t size)
{
FlagLock lock(spin_lock);
parent.dealloc_range(base, size);
}
};
};
} // namespace snmalloc

View File

@@ -0,0 +1,42 @@
#pragma once
#include "../ds/ds.h"
#include "empty_range.h"
namespace snmalloc
{
/**
* Makes the supplied ParentRange into a global variable.
*/
struct StaticRange
{
template<typename ParentRange = EmptyRange<>>
class Type : public StaticParent<ParentRange>
{
using StaticParent<ParentRange>::parent;
public:
static constexpr bool Aligned = ParentRange::Aligned;
static_assert(
ParentRange::ConcurrencySafe,
"StaticRange 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);
}
};
};
} // namespace snmalloc