]> git.mdlowis.com Git - archive/atc.git/commitdiff
Started a more general implementation of splaytree
authorMichael D. Lowis <mike@mdlowis.com>
Thu, 9 Apr 2015 02:07:31 +0000 (22:07 -0400)
committerMichael D. Lowis <mike@mdlowis.com>
Thu, 9 Apr 2015 02:07:31 +0000 (22:07 -0400)
source/runtime/heap.c
source/runtime/heap.h
source/runtime/splaytree.c
source/runtime/splaytree.h
tests/test_heap.c
tests/test_splaytree.c

index f4be807fea1a3f61c49d04a09ab25e6a4eda90a1..63316692844df9b540084558e8ed8a12870f3e73 100644 (file)
@@ -5,25 +5,46 @@
 #include "heap.h"
 #include <stdlib.h>
 
-heap_t* heap_create(void)
+static int range_compare(uintptr_t val, uintptr_t start, uintptr_t end)
 {
-    return (heap_t*)calloc(1u, sizeof(heap_t));;
+    if (val < start)
+        return -1;
+    else if (val >= end)
+        return 1;
+    else
+        return 0;
 }
 
-static void destroy_large_blocks(block_t* current) {
-    while (NULL != current) {
-        block_t* deadite = current;
-        current = current->next;
-        free(deadite);
-    }
+static int segment_compare(uintptr_t key, segment_t* seg)
+{
+    uintptr_t start = (uintptr_t)(seg->start);
+    uintptr_t end   = (uintptr_t)(seg->end);
+    return range_compare(key, start, end);
+}
+
+static int block_compare(uintptr_t key, block_t* block)
+{
+    uintptr_t start = (uintptr_t)(block->data);
+    uintptr_t end   = (uintptr_t)(start + block->size);
+    return range_compare(key, start, end);
+}
+
+heap_t* heap_create(void)
+{
+    heap_t* heap = (heap_t*)calloc(1u, sizeof(heap_t));
+    heap->segments = splaytree_create((del_fn_t)segment_destroy, (cmp_fn_t)segment_compare);
+    heap->blocks   = splaytree_create((del_fn_t)free, (cmp_fn_t)block_compare);
+    heap->greylist = NULL;
+    return heap;
 }
 
 void heap_destroy(heap_t* heap)
 {
     unsigned int i;
     /* Free all the large blocks */
-    destroy_large_blocks(heap->blocks);
-    destroy_large_blocks(heap->greylist);
+    splaytree_destroy(heap->segments);
+    splaytree_destroy(heap->blocks);
+    splaytree_destroy(heap->greylist);
     /* Free all of the small block segments */
     for (i = 0; i < NUM_HEAP_STACKS; i++) {
         segment_destroy(heap->heaps[i].available);
@@ -37,8 +58,10 @@ static void* allocate_small_block(heap_t* heap, uintptr_t num_slots)
     void* object;
     uintptr_t index = (num_slots >= MIN_NUM_SLOTS) ? (num_slots - HEAP_INDEX_OFFSET) : 0;
     /* If we dont have any available segments, allocate a new one */
-    if (NULL == heap->heaps[index].available)
+    if (NULL == heap->heaps[index].available) {
         heap->heaps[index].available = segment_create(num_slots, heap->heaps[index].available);
+        splaytree_insert(heap->segments, (uintptr_t)&(heap->heaps[index].available->start[0]), heap->heaps[index].available);
+    }
     /* Allocate the object */
     object = segment_alloc(heap->heaps[index].available);
     /* If we filled it up then move it to the full list */
@@ -55,9 +78,8 @@ static void* allocate_large_block(heap_t* heap, uintptr_t num_slots)
 {
     uintptr_t size = (num_slots * sizeof(uintptr_t));
     block_t* blk = (block_t*)malloc(sizeof(block_t) + size);
-    blk->next = heap->blocks;
     blk->size = size;
-    heap->blocks = blk;
+    splaytree_insert(heap->blocks, (uintptr_t)&blk->data[0], blk);
     return (&blk->data[0]);
 }
 
@@ -75,69 +97,27 @@ void* heap_allocate(heap_t* heap, uintptr_t num_slots)
 void heap_start_collection(heap_t* heap)
 {
     heap->greylist = heap->blocks;
-    heap->blocks = NULL;
-    for (uintptr_t i = 0; i < NUM_HEAP_STACKS; i++) {
-        for(segment_t* curr = heap->heaps[i].available; curr != NULL; curr = curr->next) {
-            segment_clear_map(heap->heaps[i].available);
-        }
-    }
+    heap->blocks   = splaytree_create((del_fn_t)free, (cmp_fn_t)block_compare);
 }
 
 void heap_finish_collection(heap_t* heap)
 {
-    destroy_large_blocks(heap->greylist);
-    heap->greylist = NULL;
-}
-
-static void* subheap_find_and_mark(heap_t* heap, uintptr_t addr) {
-//    void* obj = NULL;
-//    for (uintptr_t i = 0; i < NUM_HEAP_STACKS; i++) {
-//        for(segment_t* curr = heap->heaps[i].available; curr != NULL; curr = curr->next) {
-//            obj = segment_find_and_mark(heap->heaps[i].available, addr);
-//            if (NULL != obj) {
-//                i = NUM_HEAP_STACKS;
-//                break;
-//            }
-//        }
-//    }
-//    return obj;
-    (void)heap;
-    (void)addr;
-    return NULL;
-}
-
-static void* block_find_and_mark(heap_t* heap, uintptr_t addr) {
-//    void* obj = NULL;
-//    block_t* prev = NULL;
-//    block_t* curr = heap->greylist;
-//    while (curr != NULL) {
-//        uintptr_t start = (uintptr_t)&(curr->data[0]);
-//        uintptr_t end   = start + curr->size;
-//        if ((start <= addr) && (addr < end)) {
-//            /* Remove it from the grey list */
-//            if (prev == NULL)
-//                heap->greylist = curr->next;
-//            else
-//                prev->next = curr->next;
-//            /* Add it to the in-use list and break */
-//            curr->next = heap->blocks;
-//            heap->blocks = curr->next;
-//            break;
-//        }
-//        prev = curr;
-//        curr = curr->next;
-//    }
-//    return obj;
-    (void)heap;
-    (void)addr;
-    return NULL;
+    splaytree_destroy(heap->greylist);
 }
 
 void* heap_find_and_mark(heap_t* heap, uintptr_t addr)
 {
-    void* obj = subheap_find_and_mark(heap, addr);
-    if (NULL == obj)
-        obj = block_find_and_mark(heap, addr);
+    void* obj = NULL;
+    segment_t* seg = splaytree_lookup(heap->segments, addr);
+    if (NULL != seg) {
+        obj = segment_find_and_mark(seg, addr);
+    } else {
+        block_t* block = splaytree_delete(heap->greylist, addr);
+        if (NULL != block) {
+            splaytree_insert(heap->blocks, addr, block);
+            obj = &block->data[0];
+        }
+    }
     return obj;
 }
 
index 9544b8e309e8b5c71284565da31b267055881985..7779c8ddb7d0873b8ef257b683a86838b3c2ac52 100644 (file)
@@ -6,6 +6,7 @@
 #define HEAP_H
 
 #include "segment.h"
+#include "splaytree.h"
 
 #define MIN_NUM_SLOTS (1u)
 
@@ -16,7 +17,6 @@
 #define NUM_HEAP_STACKS (MAX_NUM_SLOTS)
 
 typedef struct block_t {
-    struct block_t* next;
     uintptr_t size;
     uintptr_t data[];
 } block_t;
@@ -26,8 +26,9 @@ typedef struct {
         segment_t* available;
         segment_t* full;
     } heaps[NUM_HEAP_STACKS];
-    block_t* blocks;
-    block_t* greylist;
+    splaytree_t* segments;
+    splaytree_t* blocks;
+    splaytree_t* greylist;
 } heap_t;
 
 heap_t* heap_create(void);
index 79114ab5427a1b6ecf4cfebbd5b828f03fb9dd00..0f761cfa223d93ad04f78c7ff38d685a6bbbeda7 100644 (file)
 #include "splaytree.h"
 #include <stdlib.h>
 
-splaytree_t* splaytree_create(void)
-{
-    splaytree_t* splaytree = (splaytree_t*)malloc(sizeof(splaytree_t));
-    splaytree->root = NULL;
-    return splaytree;
-}
-
-static void destroy_node(node_t* node)
-{
-    if (NULL != node) {
-        destroy_node(node->left);
-        destroy_node(node->right);
-        free(node);
-    }
-}
-
-void splaytree_destroy(splaytree_t* tree)
-{
-    destroy_node(tree->root);
-    free(tree);
-}
-
-static node_t* create_node(node_type_t tag, void* value)
+static node_t* create_node(void* value)
 {
     node_t* node = (node_t*)malloc(sizeof(node_t*));
-    node->tag = tag;
-    node->ptr.raw = value;
-    node->left = NULL;
-    node->right = NULL;
+    node->value  = value;
+    node->left   = NULL;
+    node->right  = NULL;
     return node;
 }
 
-static uintptr_t get_start_addr(node_t* curr)
+static node_t** next_node(splaytree_t* tree, node_t* curr, uintptr_t address)
 {
-    if (curr->tag == SEGMENT)
-        return (uintptr_t)(curr->ptr.segment->start);
+    if (tree->compare(address, curr->value) < 0)
+        return &(curr->left);
     else
-        return (uintptr_t)(curr->ptr.block->data);
+        return &(curr->right);
 }
 
-static uintptr_t get_end_addr(node_t* curr)
+splaytree_t* splaytree_create(del_fn_t delfn, cmp_fn_t cmp_fn)
 {
-    if (curr->tag == SEGMENT)
-        return (uintptr_t)(curr->ptr.segment->end);
-    else
-        return (uintptr_t)(curr->ptr.block->data + curr->ptr.block->size);
+    splaytree_t* tree = (splaytree_t*)malloc(sizeof(splaytree_t));
+    tree->destroy = delfn;
+    tree->compare = cmp_fn;
+    tree->root = NULL;
+    return tree;
 }
 
-static node_t** next_node(node_t* curr, uintptr_t address)
+void splaytree_destroy(splaytree_t* tree)
 {
-    uintptr_t curr_address = get_start_addr(curr);
-    if (address < curr_address)
-        return &(curr->left);
-    else
-        return &(curr->right);
+    (void)tree;
 }
 
-void splaytree_insert(splaytree_t* tree, node_type_t tag, void* value)
+void splaytree_insert(splaytree_t* tree, uintptr_t key, void* value)
 {
-    /* Get the address of the start of the range */
-    uintptr_t address;
-    if (SEGMENT == tag)
-        address = (uintptr_t)((segment_t*)value)->start;
-    else
-        address = (uintptr_t)((block_t*)value)->data;
     /* Insert the item into the tree */
-    if (tree->root == NULL)
-        tree->root = create_node(tag, value);
-    else {
+    if (tree->root == NULL) {
+        tree->root = create_node(value);
+    else {
         node_t** current = &(tree->root);
         while(*current != NULL) {
-            current = next_node(*current, address);
+            current = next_node(tree, *current, key);
         }
-        *current = create_node(tag, value);
+        *current = create_node(value);
     }
 }
 
-node_type_t splaytree_lookup(splaytree_t* tree, uintptr_t address, void** value)
+void* splaytree_lookup(splaytree_t* tree, uintptr_t key)
 {
-    node_type_t tag = NONE;
     node_t* current = tree->root;
-    while(current != NULL) {
-        uintptr_t start = get_start_addr(current);
-        uintptr_t end   = get_end_addr(current);
-        if ((start <= address) && (address < end)) {
-            tag = current->tag;
-            *value = current->ptr.raw;
-            break;
-        } else if (start < address) {
+    while (current != NULL) {
+        int cmp_val = tree->compare(key, current);
+        if (cmp_val == 0)
+            return current->value;
+        else if (cmp_val < 0)
             current = current->left;
-        } else {
+        else
             current = current->right;
-        }
     }
-    return tag;
+    return NULL;
 }
 
-void splaytree_delete(splaytree_t* tree, uintptr_t address)
+void* splaytree_delete(splaytree_t* tree, uintptr_t key)
 {
     (void)tree;
-    (void)address;
+    (void)key;
+    return NULL;
 }
 
index 71dc69083314fea9959ea118d81fbbefd91482a8..edd2faaf2b3ae41443d41994a49312ab8c8e7547 100644 (file)
@@ -6,33 +6,31 @@
 #define SPLAYTREE_H
 
 #include <stdint.h>
-#include "heap.h"
 
-typedef enum { SEGMENT, BLOCK, NONE } node_type_t;
+typedef void (*del_fn_t)(void* value);
+
+typedef int (*cmp_fn_t)(uintptr_t key, void* value);
 
 typedef struct node_t {
-    node_type_t tag;
-    union {
-        segment_t* segment;
-        block_t* block;
-        void* raw;
-    } ptr;
+    void* value;
     struct node_t* left;
     struct node_t* right;
 } node_t;
 
 typedef struct splaytree_t {
-    node_t*   root;
+    del_fn_t destroy;
+    cmp_fn_t compare;
+    node_t*  root;
 } splaytree_t;
 
-splaytree_t* splaytree_create(void);
+splaytree_t* splaytree_create(del_fn_t delfn, cmp_fn_t cmp_fn);
 
 void splaytree_destroy(splaytree_t* tree);
 
-void splaytree_insert(splaytree_t* tree, node_type_t tag, void* value);
+void splaytree_insert(splaytree_t* tree, uintptr_t key, void* value);
 
-node_type_t splaytree_lookup(splaytree_t* tree, uintptr_t address, void** value);
+void* splaytree_lookup(splaytree_t* tree, uintptr_t key);
 
-void splaytree_delete(splaytree_t* tree, uintptr_t address);
+void* splaytree_delete(splaytree_t* tree, uintptr_t key);
 
 #endif /* SPLAYTREE_H */
index 5e46ad5ca37a9ac3eb98dd2342af689fbb9fb843..4667639da1347e97e098f36316e5eef5e7dcbf56 100644 (file)
@@ -42,10 +42,11 @@ TEST_SUITE(Heap) {
     }
 
     TEST(Verify_Allocate_should_allocate_a_large_block_if_the_number_of_slots_is_greater_than_the_max) {
-        heap_t* heap = heap_create();
-        CHECK(NULL != heap_allocate(heap, 65));
-        CHECK(heap->blocks != NULL);
-        CHECK(heap->blocks->next == NULL);
-        heap_destroy(heap);
+        CHECK(false);
+        //heap_t* heap = heap_create();
+        //CHECK(NULL != heap_allocate(heap, 65));
+        //CHECK(heap->blocks != NULL);
+        //CHECK(heap->blocks->next == NULL);
+        //heap_destroy(heap);
     }
 }
index e4a783ce8dfd138d2671daaad6423e335b5c0fe5..6223e20dd8080045f637d91033e5841f58575117 100644 (file)
@@ -4,11 +4,11 @@
 TEST_SUITE(SplayTree) {
     /* Verify: splaytree_create
      *************************************************************************/
-    TEST(Verify_Create_allocates_and_initializes_an_empty_tree) {
-        splaytree_t* tree = splaytree_create();
-        CHECK(tree->root    == NULL);
-        splaytree_destroy(tree);
-    }
+    //TEST(Verify_Create_allocates_and_initializes_an_empty_tree) {
+    //    splaytree_t* tree = splaytree_create();
+    //    CHECK(tree->root    == NULL);
+    //    splaytree_destroy(tree);
+    //}
 
     /* Verify: splaytree_create
      *************************************************************************/