Merge pull request #37 from Microsoft/invalid_pointer
Add an explicit invalid pointer type.
This commit is contained in:
@@ -6,29 +6,61 @@
|
||||
|
||||
namespace snmalloc
|
||||
{
|
||||
template<class T, uintptr_t Terminator = 0>
|
||||
/**
|
||||
* Invalid pointer class. This is similar to `std::nullptr_t`, but allows
|
||||
* other values.
|
||||
*/
|
||||
template<uintptr_t Sentinel>
|
||||
struct InvalidPointer
|
||||
{
|
||||
/**
|
||||
* Equality comparison. Two invalid pointer values with the same sentinel
|
||||
* are always the same, invalid pointer values with different sentinels are
|
||||
* always different.
|
||||
*/
|
||||
template<uintptr_t OtherSentinel>
|
||||
constexpr bool operator==(const InvalidPointer<OtherSentinel>&)
|
||||
{
|
||||
return Sentinel == OtherSentinel;
|
||||
}
|
||||
/**
|
||||
* Equality comparison. Two invalid pointer values with the same sentinel
|
||||
* are always the same, invalid pointer values with different sentinels are
|
||||
* always different.
|
||||
*/
|
||||
template<uintptr_t OtherSentinel>
|
||||
constexpr bool operator!=(const InvalidPointer<OtherSentinel>&)
|
||||
{
|
||||
return Sentinel != OtherSentinel;
|
||||
}
|
||||
/**
|
||||
* Implicit conversion, creates a pointer with the value of the sentinel.
|
||||
* On CHERI and other provenance-tracking systems, this is a
|
||||
* provenance-free integer and so will trap if dereferenced, on other
|
||||
* systems the sentinel should be a value in unmapped memory.
|
||||
*/
|
||||
template<typename T>
|
||||
operator T*()
|
||||
{
|
||||
return reinterpret_cast<T*>(Sentinel);
|
||||
}
|
||||
};
|
||||
|
||||
template<class T, class Terminator = std::nullptr_t>
|
||||
class DLList
|
||||
{
|
||||
private:
|
||||
// Single point to perform this cast.
|
||||
// Would like this to be a constexpr, but reinterpret cast is not allowed in
|
||||
// constexpr.
|
||||
static inline T* terminator()
|
||||
{
|
||||
return (T*)Terminator;
|
||||
}
|
||||
|
||||
static_assert(
|
||||
std::is_same<decltype(T::prev), T*>::value, "T->prev must be a T*");
|
||||
static_assert(
|
||||
std::is_same<decltype(T::next), T*>::value, "T->next must be a T*");
|
||||
|
||||
T* head = terminator();
|
||||
T* head = Terminator();
|
||||
|
||||
public:
|
||||
bool is_empty()
|
||||
{
|
||||
return head == terminator();
|
||||
return head == Terminator();
|
||||
}
|
||||
|
||||
T* get_head()
|
||||
@@ -40,7 +72,7 @@ namespace snmalloc
|
||||
{
|
||||
T* item = head;
|
||||
|
||||
if (item != terminator())
|
||||
if (item != Terminator())
|
||||
remove(item);
|
||||
|
||||
return item;
|
||||
@@ -53,9 +85,9 @@ namespace snmalloc
|
||||
#endif
|
||||
|
||||
item->next = head;
|
||||
item->prev = terminator();
|
||||
item->prev = Terminator();
|
||||
|
||||
if (head != terminator())
|
||||
if (head != Terminator())
|
||||
head->prev = item;
|
||||
|
||||
head = item;
|
||||
@@ -70,10 +102,10 @@ namespace snmalloc
|
||||
debug_check_contains(item);
|
||||
#endif
|
||||
|
||||
if (item->next != terminator())
|
||||
if (item->next != Terminator())
|
||||
item->next->prev = item->prev;
|
||||
|
||||
if (item->prev != terminator())
|
||||
if (item->prev != Terminator())
|
||||
item->prev->next = item->next;
|
||||
else
|
||||
head = item->next;
|
||||
@@ -91,7 +123,7 @@ namespace snmalloc
|
||||
|
||||
while (curr != item)
|
||||
{
|
||||
assert(curr != terminator());
|
||||
assert(curr != Terminator());
|
||||
curr = curr->next;
|
||||
}
|
||||
#else
|
||||
@@ -105,7 +137,7 @@ namespace snmalloc
|
||||
debug_check();
|
||||
T* curr = head;
|
||||
|
||||
while (curr != terminator())
|
||||
while (curr != Terminator())
|
||||
{
|
||||
assert(curr != item);
|
||||
curr = curr->next;
|
||||
@@ -119,9 +151,9 @@ namespace snmalloc
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
T* item = head;
|
||||
T* prev = terminator();
|
||||
T* prev = Terminator();
|
||||
|
||||
while (item != terminator())
|
||||
while (item != Terminator())
|
||||
{
|
||||
assert(item->prev == prev);
|
||||
prev = item;
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace snmalloc
|
||||
}
|
||||
};
|
||||
|
||||
using SlabList = DLList<SlabLink, UINTPTR_MAX>;
|
||||
using SlabList = DLList<SlabLink, InvalidPointer<UINTPTR_MAX>>;
|
||||
|
||||
static_assert(
|
||||
sizeof(SlabLink) <= MIN_ALLOC_SIZE,
|
||||
|
||||
Reference in New Issue
Block a user