view src/insert_verification/akashaCS.c @ 26:cf7cbe70404f

WIP: Trying implement copying GC...
author Yasutaka Higa <e115763@ie.u-ryukyu.ac.jp>
date Sat, 16 Apr 2016 09:44:48 +0900
parents 38ba1606e62d
children a416dd4093cf
line wrap: on
line source

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

#include "akashaLLRBContext.h"

extern __code initLLRBContext(struct Context*, enum Code);

/* utils */

void* akashaMalloc(struct Context* akashaContext, unsigned int size) {
    akashaContext->data[++akashaContext->dataNum] = akashaContext->heap;
    akashaContext->heap += size;
    return akashaContext->data[akashaContext->dataNum];
}

bool eqNode(struct Node* n1, struct Node* n2) {
    if ((n1 == NULL) && (n2 == NULL))  return true;
    if (n1->key   != n2->key)          return false;
    if (n1->value != n2->value)        return false;
    if (n1->color != n2->color)        return false;
    if (!eqNode(n1->left,  n2->left))  return false;
    if (!eqNode(n1->right, n2->right)) return false;
    return true;
}

bool eqTree(struct Tree* t1, struct Tree* t2) {
    if ((t1 == NULL) && (t2 == NULL))      return true;
    if (t1->next   != t2->next)            return false;
    if (t2->result != t2->result)          return false;
    if (!eqNode(t1->root,    t2->root))    return false;
    if (!eqNode(t1->current, t2->current)) return false;
    if (!eqNode(t1->deleted, t2->deleted)) return false;
    return true;
}


bool eqIter(struct Iterator* iter1, struct Iterator* iter2) {
    if (iter1->head->val != iter2->head->val)         return false;
    if (iter1->last->val != iter2->last->val)         return false;
    if (iter1->iteratedValue != iter2->iteratedValue) return false;
    if (!eqTree(iter1->tree, iter2->tree))            return false;

    struct IterElem *ie1 = iter1->head->next;
    struct IterElem *ie2 = iter2->head->next;

    while (ie1->val != iter1->head->val) {
        if (ie1->val != ie2->val) return false;
        ie1 = ie1->next;
        ie2 = ie2->next;
    }

    if ((iter1->previousDepth == NULL) && (iter2->previousDepth == NULL)) return true;
    return eqIter(iter1->previousDepth, iter2->previousDepth);
}


/* C function */

struct Node* nodeDeepCopy(struct Context* newContext, struct Node* oldNode) {
    if (oldNode == NULL) return NULL;

    struct Allocate* allocate = &newContext->data[Allocate]->allocate;
    allocate->size = sizeof(Node);
    allocator(newContext);

    struct Node* newNode = (struct Node*)newContext->data[newContext->dataNum];
    newNode->next  = oldNode->next;
    newNode->key   = oldNode->key;
    newNode->value = oldNode->value;
    newNode->color = oldNode->color;

    if (oldNode->left != NULL)  {
        newNode->left = nodeDeepCopy(newContext, oldNode->left);
    } else {
        newNode->left = NULL;
    }

    if (oldNode->right != NULL)  {
        newNode->right = nodeDeepCopy(newContext, oldNode->right);
    } else {
        newNode->right = NULL;
    }

    return newNode;
}

struct Tree* treeDeepCopy(struct Context* newContext, struct Tree* oldTree) {
    if (oldTree == NULL) return NULL;

    struct Allocate* allocate = &newContext->data[Allocate]->allocate;
    allocate->size = sizeof(Node);
    allocator(newContext);

    struct Tree* newTree = (struct Tree*)newContext->data[newContext->dataNum];
    newTree->next        = oldTree->next;
    newTree->result      = oldTree->result;
    newTree->root        = nodeDeepCopy(newContext, oldTree->root);
    newTree->current     = nodeDeepCopy(newContext, oldTree->current);
    newTree->deleted     = nodeDeepCopy(newContext, oldTree->deleted);

    return newTree;
}

void iterElemDeepCopy(struct Context* newContext, struct Iterator* newIter, struct Iterator *oldIter) {
    newIter->head = (struct IterElem*)akashaMalloc(newContext, sizeof(struct IterElem));

    newIter->head->val = oldIter->head->val;
    struct IterElem *oldElem = oldIter->head;
    struct IterElem *newElem = newIter->head;
    while (1) {
        if (oldElem->next->val == oldIter->head->val) break;
        newElem->next = akashaMalloc(newContext, sizeof(struct IterElem));

        newElem->next->val = oldElem->next->val;
        newElem = newElem->next;
        oldElem = oldElem->next;
    }
    newElem->next = newIter->head;

    while (newElem->val != oldIter->last->val) {
        newElem = newElem->next;
    }
    newIter->last = newElem;
}

void iterDeepCopy(struct Context* newContext, struct Iterator* newIter, struct Iterator* oldIter) {
    newIter->tree = treeDeepCopy(newContext, oldIter->tree);

    newIter->iteratedValue = oldIter->iteratedValue;
    iterElemDeepCopy(newContext, newIter, oldIter);

    if (oldIter->previousDepth != NULL) {
        newIter->previousDepth = akashaMalloc(newContext, sizeof(struct Iterator));
        iterDeepCopy(newContext, newIter->previousDepth, oldIter->previousDepth);
    } else {
        newIter->previousDepth = NULL;
    }
}

void memoryRefresh(struct Context* oldContext) {
    if (oldContext->node_stack->num != 0) { abort(); }
    if (oldContext->code_stack->num != 0) { abort(); }

    struct Context* newContext = (struct Context*)malloc(sizeof(struct Context));

    newContext->dataLimit = oldContext->dataLimit;
    newContext->heapLimit = oldContext->heapLimit;
    newContext->code      = oldContext->code;
    newContext->data      = malloc(newContext->dataLimit * sizeof(union Data*));
    newContext->heapStart = malloc(newContext->heapLimit);
    newContext->codeNum   = Exit;
    newContext->heap      = newContext->heapStart;
    memset(newContext->heapStart, newContext->heapLimit, 0);

    printf("reallocation! : %lu\n", newContext->heapLimit);

    newContext->data[Allocate] = newContext->heap;
    newContext->heap += sizeof(struct Allocate);
    newContext->data[Allocate]->allocate = oldContext->data[Allocate]->allocate;

    newContext->data[Tree] = newContext->heap;
    newContext->heap += sizeof(struct Tree);

    newContext->data[Node] = newContext->heap;
    newContext->heap += sizeof(struct Node);

    newContext->data[Iter] = newContext->heap;
    newContext->heap += sizeof(struct Iterator);

    newContext->dataNum = Iter;

    newContext->data[Node]->node = *nodeDeepCopy(newContext, &oldContext->data[Node]->node);
    newContext->data[Tree]->tree = *treeDeepCopy(newContext, &oldContext->data[Tree]->tree);
    if (!eqTree(&newContext->data[Tree]->tree,     &oldContext->data[Tree]->tree)) abort();
    iterDeepCopy(newContext, &newContext->data[Iter]->iterator, &oldContext->data[Iter]->iterator);
    if (!eqIter(&newContext->data[Iter]->iterator, &oldContext->data[Iter]->iterator)) abort();

    newContext->node_stack = oldContext->node_stack;
    newContext->code_stack = oldContext->code_stack;
    newContext->next       = oldContext->next;
    free(oldContext->data);
    free(oldContext->heapStart);
    *oldContext = *newContext;
}

void validateNodePointer(struct Node* node) {
    if (node == NULL) return;
    validateNodePointer(node->left);
    validateNodePointer(node->right);
}

void validateTreePointer(struct Tree* tree) {
    if (tree == NULL) return;
    validateNodePointer(tree->root);
    validateNodePointer(tree->current);
    validateNodePointer(tree->deleted);
}


void findInvalidPointer(struct Context* context) {
    validateNodePointer(&context->data[Node]->node);
    validateTreePointer(&context->data[Tree]->tree);
}

/* Code Segments */

__code meta(struct Context* context, enum Code next) {
    if (next == Put) {
        findInvalidPointer(context);
        if (context->dataNum > (context->dataLimit * 0.9)) memoryRefresh(context);
    }
    findInvalidPointer(context);
    context->prev = next;
    goto (context->code[next])(context);
}

__code startCode(enum Code next) {
    struct Context* context = (struct Context*)malloc(sizeof(struct Context));

    goto initLLRBContext(context, next);
}

__code exitCode(struct Context* context) {
    free(context->code);
    free(context->data);
    free(context->heapStart);
    goto exit(0);
}