Skip to content

Commit

Permalink
Reimplement STB::Heap using STB::List
Browse files Browse the repository at this point in the history
  • Loading branch information
AnotherJohnH committed Dec 8, 2024
1 parent 40a4fb2 commit 45e5302
Show file tree
Hide file tree
Showing 8 changed files with 221 additions and 88 deletions.
36 changes: 15 additions & 21 deletions STB/Heap.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,12 @@
#include <cstddef>
#include <new>

#include "STB/List.h"

namespace STB {

template <typename TYPE>
struct HeapElem
{
TYPE* next{nullptr};
};
using HeapElem = typename STB::List<TYPE>::Elem;

template <typename TYPE, size_t SIZE>
class Heap
Expand All @@ -43,36 +42,35 @@ class Heap
}

//! Check if heap is empty
bool empty() const { return free_list == nullptr; }
bool empty() const { return free_list.empty(); }

//! Get number of objects that have been allocated
size_t allocated() const { return num_alloc; }
size_t allocated() const { return SIZE - free_list.size(); }

//! Return the heap index for an element
size_t index(const TYPE* object_) const { return object_ - heap; }

//! Reset the heap to nothing allocated
//! destructors are not called on any active allocations
void reset()
{
free_list = nullptr;
num_alloc = SIZE;
free_list.clear();

for(size_t i = 0; i < SIZE; ++i)
{
free(&heap[i]);
free_list.push_front(&heap[i]);
}
}

//! Allocate a new object
TYPE* alloc()
{
if (empty())
return nullptr;
TYPE* object = free_list.front();

TYPE* object = free_list;
free_list = free_list->next;
if (object == nullptr)
return nullptr;

++num_alloc;
free_list.pop_front();

return new (object) TYPE();
}
Expand All @@ -82,16 +80,12 @@ class Heap
{
object_->~TYPE();

object_->next = free_list;
free_list = object_;

--num_alloc;
free_list.push_front(object_);
}

private:
TYPE heap[SIZE];
TYPE* free_list{};
size_t num_alloc{SIZE};
List<TYPE> free_list;
TYPE heap[SIZE];
};

} // namespace STB
134 changes: 75 additions & 59 deletions STB/List.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,137 +33,153 @@ template <typename TYPE>
class List
{
public:
//! Base class for list elements
class Element
//! Base class for list elems
class Elem
{
friend class List;

public:
TYPE* nextElem() const { return next; }

private:
TYPE* next{nullptr};
};

//! Iterator for list elements
class iterator
template <typename T>
class iterator_impl
{
public:
iterator(TYPE* ptr_)
iterator_impl(T* ptr_)
: ptr(ptr_)
{}

iterator& operator++()
iterator_impl& operator++()
{
ptr = ptr->next;
return *this;
}

bool operator==(const iterator& other) const { return ptr == other.ptr; }
bool operator==(const iterator_impl& other) const { return ptr == other.ptr; }

bool operator!=(const iterator& other) const { return ptr != other.ptr; }
bool operator!=(const iterator_impl& other) const { return ptr != other.ptr; }

TYPE& operator*() { return *ptr; }
T& operator*() { return *ptr; }

private:
TYPE* ptr;
T* ptr;
};

using iterator = iterator_impl<TYPE>;
using const_iterator = iterator_impl<const TYPE>;

//! Test for empty list
bool empty() const { return first == nullptr; }

//! Return the number of elems in the list
size_t size() const { return n; }

//! Returns pointer to the first item in the list
TYPE* front() const { return first; }

//! Returns pointer to the last item in the list
// XXX O(n)
TYPE* back() const
{
TYPE* back;

for(back = first; back->next != nullptr; back = back->next);

return back;
}

//! Return an iterator for the first element in the list
iterator begin() { return iterator(first); }
//! Return an iterator for the first elem in the list
iterator begin() { return iterator(first); }

//! return an iterator for the end of the list
iterator end() { return iterator(nullptr); }

//! Return an iterator for the first elem in the list
const_iterator begin() const { return const_iterator(first); }

//! Remove the first element from the list
//! return an iterator for the end of the list
const_iterator end() const { return const_iterator(nullptr); }


//! Clear list to empty
void clear()
{
first = nullptr;
n = 0;
}

//! Remove the first elem from the list
void pop_front()
{
assert(!empty());
assert(not empty());

first = first->next;
--n;
}

//! Remove an element from the list
//! Remove the last elem from the list
void pop_back()
{
assert(not empty());

remove(back());
}

//! Remove an elem from the list
// XXX O(n)
void remove(TYPE* element)
void remove(TYPE* elem)
{
TYPE** prev = &first;

for(TYPE* e = first; e; e = e->next)
{
if (element == e)
if (elem == e)
{
*prev = e->next;
e->next = nullptr;
--n;
return;
}

prev = &e->next;
}
}

//! Insert a new element at the front of the list
void push_front(TYPE* element)
//! Insert a new elem at the front of the list
void push_front(TYPE* elem)
{
assert(element != first);
assert(elem != first);

elem->next = first;
first = elem;

element->next = first;
first = element;
++n;
}

//! Insert a new element at the back of the list
//! Insert a new elem at the back of the list
// XXX O(n)
void push_back(TYPE* element)
void push_back(TYPE* elem)
{
elem->next = nullptr;

if (first == nullptr)
{
first = element;
first = elem;
}
else
{
TYPE* prev;

for(prev = first; prev->next != nullptr; prev = prev->next);

prev->next = element;
}
}

//! Insert a new element into the list
// item must not already be in the list
void insert(TYPE* element)
{
TYPE* prev = nullptr;
TYPE* e;

for(e = first; e; e = e->next)
{
if (*element <= *e) break;

prev = e;
back()->next = elem;
}

assert(element != e);
element->next = e;

if (prev)
{
assert(prev != element);
prev->next = element;
}
else
{
first = element;
}
++n;
}

private:
TYPE* first{nullptr};
TYPE* first{nullptr};
size_t n{0};
};

} // namespace STB
Expand Down
3 changes: 2 additions & 1 deletion STB/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ if(${PLT_NATIVE})
testMain.cpp
testEndian.cpp
testHeap.cpp
testLicense.cpp)
testLicense.cpp
testList.cpp)

target_link_libraries(test_STB PLT STB)

Expand Down
8 changes: 4 additions & 4 deletions STB/test/testHeap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ TEST(STB_Heap, basic)
Object* obj = heap.alloc();

EXPECT_NE(nullptr, obj);
EXPECT_EQ(nullptr, obj->next);
EXPECT_EQ(nullptr, obj->nextElem());

EXPECT_FALSE(heap.empty());
EXPECT_EQ(1, heap.allocated());
Expand All @@ -57,23 +57,23 @@ TEST(STB_Heap, full)
size_t one_idx = heap.index(one);

EXPECT_NE(nullptr, one);
EXPECT_EQ(nullptr, one->next);
EXPECT_EQ(nullptr, one->nextElem());
EXPECT_FALSE(heap.empty());
EXPECT_EQ(1, heap.allocated());

Object* two = heap.alloc();
size_t two_idx = heap.index(two);

EXPECT_NE(nullptr, two);
EXPECT_EQ(nullptr, two->next);
EXPECT_EQ(nullptr, two->nextElem());
EXPECT_FALSE(heap.empty());
EXPECT_EQ(2, heap.allocated());

Object* three = heap.alloc();
size_t three_idx = heap.index(three);

EXPECT_NE(nullptr, three);
EXPECT_EQ(nullptr, three->next);
EXPECT_EQ(nullptr, three->nextElem());
EXPECT_TRUE(heap.empty());
EXPECT_EQ(3, heap.allocated());

Expand Down
Loading

0 comments on commit 45e5302

Please sign in to comment.