Allocation failure fix and test

This commit is contained in:
Léa Saviot
2018-06-28 14:50:45 +02:00
parent c208da2f90
commit 46d56ade21
17 changed files with 151 additions and 28 deletions

View File

@@ -6,11 +6,9 @@
class AdditionNode : public ExpressionNode {
public:
#if TREE_LOGGING
const char * description() const override {
return "Addition";
}
#endif
size_t size() const override {
return sizeof(AdditionNode);
@@ -23,8 +21,11 @@ public:
return result;
}
int numberOfChildren() const override {
return 2;
int numberOfChildren() const override { return m_numberOfChildren; }
void incrementNumberOfChildren() override { m_numberOfChildren++; }
void decrementNumberOfChildren() override {
assert(m_numberOfChildren > 0);
m_numberOfChildren--;
}
/*
Expression simplify() override {
@@ -34,6 +35,8 @@ public:
}
}
*/
private:
int m_numberOfChildren;
};
class AdditionRef : public ExpressionReference<AdditionNode> {
@@ -41,8 +44,8 @@ public:
AdditionRef(ExpressionRef e1, ExpressionRef e2) :
ExpressionReference<AdditionNode>()
{
addOperand(e2);
addOperand(e1);
addChild(e2);
addChild(e1);
}
};

View File

@@ -2,6 +2,8 @@
#define ALLOCATION_FAILED_EXPRESSION_NODE_H
#include "expression_node.h"
#include "expression_reference.h"
#include <stdio.h>
class AllocationFailedExpressionNode : public ExpressionNode {
public:
@@ -12,6 +14,7 @@ public:
size_t size() const override { return sizeof(AllocationFailedExpressionNode); }
const char * description() const override { return "Allocation Failed"; }
int numberOfChildren() const override { return 0; }
bool isAllocationFailure() const override { return true; }
};
class AllocationFailedExpressionRef : public ExpressionReference<AllocationFailedExpressionNode> {

View File

@@ -0,0 +1,21 @@
#ifndef ALLOCATION_FAILED_LAYOUT_NODE_H
#define ALLOCATION_FAILED_LAYOUT_NODE_H
#include "layout_node.h"
#include "layout_reference.h"
class AllocationFailedLayoutNode : public LayoutNode {
public:
// TreeNode
size_t size() const override { return sizeof(AllocationFailedLayoutNode); }
const char * description() const override { return "Allocation Failed"; }
int numberOfChildren() const override { return 0; }
bool isAllocationFailure() const override { return true; }
};
class AllocationFailedLayoutRef : public LayoutReference<AllocationFailedLayoutNode> {
public:
AllocationFailedLayoutRef() : LayoutReference<AllocationFailedLayoutNode>() {}
};
#endif

8
expression_node.cpp Normal file
View File

@@ -0,0 +1,8 @@
#include "expression_node.h"
#include "expression_reference.h"
TreeNode * ExpressionNode::failedAllocationNode() {
return ExpressionRef::failedAllocationNode();
}

View File

@@ -5,6 +5,7 @@
class ExpressionNode : public TreeNode {
public:
static TreeNode * failedAllocationNode();
virtual float approximate() = 0;
ExpressionNode * child(int i) { return static_cast<ExpressionNode *>(childTreeAtIndex(i)); }
};

8
expression_reference.cpp Normal file
View File

@@ -0,0 +1,8 @@
#include "expression_reference.h"
#include "allocation_failed_expression_node.h"
template<>
TreeNode * ExpressionRef::failedAllocationNode() {
static AllocationFailedExpressionRef FailureRef;
return FailureRef.node();
}

View File

@@ -16,8 +16,12 @@ public:
return ExpressionReference<ExpressionNode>(this->node());
}
void addOperand(ExpressionReference<ExpressionNode> e) {
TreeReference<T>::addChild(e);
static TreeNode * failedAllocationNode();
void addChild(ExpressionReference<ExpressionNode> e) {
if (!this->node()->isAllocationFailure()) {
TreeReference<T>::addTreeChild(e);
}
}
ExpressionReference<ExpressionNode> childAtIndex(int i) {

View File

@@ -14,6 +14,7 @@ public:
return m_value > 1 ? "BigFloat" : "SmallFloat";
}
void setFloat(float f) { m_value = f; }
void init(float f) override { m_value = f; }
private:
float m_value;
};
@@ -21,7 +22,7 @@ private:
class FloatRef : public ExpressionReference<FloatNode> {
public:
FloatRef(float f) : ExpressionReference<FloatNode>() {
this->node()->setFloat(f);
this->uncastedNode()->init(f);
}
};

View File

@@ -18,6 +18,10 @@ public:
int numberOfChildren() const override { return m_numberOfChildren; }
void incrementNumberOfChildren() override { m_numberOfChildren++; }
void decrementNumberOfChildren() override {
assert(m_numberOfChildren > 0);
m_numberOfChildren--;
}
void moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) override {
if (this == cursor->layoutReference().node()) {
@@ -78,12 +82,12 @@ class HorizontalLayoutRef : public LayoutReference<HorizontalLayoutNode> {
public:
HorizontalLayoutRef() : LayoutReference<HorizontalLayoutNode>() {}
HorizontalLayoutRef(LayoutRef l) : LayoutReference<HorizontalLayoutNode>() {
addChild(l);
addTreeChild(l);
}
HorizontalLayoutRef(LayoutRef l1, LayoutRef l2) : LayoutReference<HorizontalLayoutNode>() {
addChild(l2);
addChild(l1);
addTreeChild(l2);
addTreeChild(l1);
}
};

View File

@@ -1,4 +1,9 @@
#include "layout_node.h"
#include "layout_reference.h"
TreeNode * LayoutNode::failedAllocationNode() {
return LayoutRef::failedAllocationNode();
}
void LayoutNode::draw() {
for (LayoutNode * child : children()) {

View File

@@ -7,6 +7,8 @@ class LayoutCursor;
class LayoutNode : public TreeNode {
public:
static TreeNode * failedAllocationNode();
/* Hierarchy */
LayoutNode * parent() const { return static_cast<LayoutNode *>(parentTree()); }

View File

@@ -1,8 +1,15 @@
#include "layout_reference.h"
#include "layout_cursor.h"
#include "allocation_failed_layout_node.h"
#include "layout_node.h"
#include "char_layout_node.h"
template<>
TreeNode * LayoutRef::failedAllocationNode() {
static AllocationFailedLayoutRef FailureRef;
return FailureRef.node();
}
template <typename T>
LayoutCursor LayoutReference<T>::cursor() const {
return LayoutCursor(this->node());

View File

@@ -18,6 +18,8 @@ public:
return LayoutReference<LayoutNode>(this->node());
}
static TreeNode * failedAllocationNode();
LayoutCursor cursor() const;
LayoutReference<LayoutNode> childAtIndex(int i) {

View File

@@ -94,25 +94,66 @@ void testCursorMoveLeft() {
assert(aChar.nodeRetainCount() == 3);
}
void testPoolAllocationFail() {
printf("Pool allocation fail test\n");
void testPoolExpressionAllocationFail() {
printf("Pool expression allocation fail test\n");
// Fill the pool for size 256
// Allocation fail
assert(TreePool::sharedPool()->numberOfNodes() == 0);
AllocationFailedExpressionRef a;
ExpressionRef::failedAllocationNode();
assert(TreePool::sharedPool()->numberOfNodes() == 1);
// Fill the pool for size 256
FloatRef f1(0.0f);
FloatRef f2(1.0f);
AdditionRef a1(f1, f2);
float result1 = a1.approximate();
assert(result1 == 1);
FloatRef f3(2.0f);
FloatRef f4(3.0f);
FloatRef f5(4.0f);
FloatRef f6(5.0f);
FloatRef f7(6.0f);
FloatRef f8(7.0f);
FloatRef f9(8.0f);
// Allocation fail
FloatRef f11(10.0f);
AdditionRef a(f11, f3);
float result = a.approximate();
assert(result == -1);
assert(ExpressionRef::failedAllocationNode()->retainCount() == 3);
f1.replaceWith(f11);
float result2 = a1.approximate();
assert(result2 == 0);
TreePool::sharedPool()->log();
}
void testPoolLayoutAllocationFail() {
printf("Pool layout allocation fail test\n");
// Fill the pool for size 256
CharLayoutRef char1('a');
LayoutRef::failedAllocationNode();
CharLayoutRef char2('b');
CharLayoutRef char3('a');
CharLayoutRef char4('b');
CharLayoutRef char5('a');
CharLayoutRef char6('b');
CharLayoutRef char7('a');
CharLayoutRef char8('b');
CharLayoutRef char9('a');
CharLayoutRef char10('b');
// Allocation fail
CharLayoutRef char11('a');
/*Expression e = ;
e.simplify*/
e.simplify*/
}
typedef void (test)();
void runTest(test t) {
assert(TreePool::sharedPool()->numberOfNodes() == 0);
// TODO add aserts on the pool size once we decide to create allocationFailureNodesFromTheStart
t();
assert(TreePool::sharedPool()->numberOfNodes() == 0);
}
int main() {
@@ -121,7 +162,7 @@ int main() {
runTest(testPoolEmpties);
runTest(testCursorCreateAndRetain);
runTest(testCursorMoveLeft);
runTest(testPoolAllocationFail);
runTest(testPoolExpressionAllocationFail);
printf("\n*******************\nEnd of tests\n*******************\n\n");
return 0;
}

View File

@@ -25,8 +25,10 @@ public:
virtual const char * description() const {
return "UNKNOWN";
}
virtual bool isAllocationFailure() const { return false; }
// Node operations
virtual void init(float f) {}
void retain() { m_referenceCounter++; }
void release();
void rename(int identifier) {
@@ -39,6 +41,7 @@ public:
TreeNode * editableRootTree();
virtual int numberOfChildren() const = 0;
virtual void incrementNumberOfChildren() {} //TODO Put an assert false
virtual void decrementNumberOfChildren() {} //TODO Put an assert false //TODO what if somebody i stealing a unary tree's only child ?
int numberOfDescendants(bool includeSelf) const;
TreeNode * childTreeAtIndex(int i) const;
int indexOfChildByIdentifier(int childID) const;

View File

@@ -15,14 +15,16 @@ public:
TreeNode * last() const { return reinterpret_cast<TreeNode *>(const_cast<char *>(m_cursor)); }
template <typename T>
T * createTreeNode() {
TreeNode * createTreeNode() {
int nodeIdentifier = generateIdentifier();
if (nodeIdentifier == -1) {
return nullptr; // TODO return static node "failedAllocation"
T::failedAllocationNode()->retain();
return T::failedAllocationNode(); // TODO return static node "failedAllocation"
}
void * ptr = alloc(sizeof(T));
if (ptr == nullptr) {
return nullptr;
T::failedAllocationNode()->retain();
return T::failedAllocationNode();
}
T * node = new(ptr) T();
node->rename(nodeIdentifier);

View File

@@ -58,9 +58,15 @@ public:
T * node() const {
// TODO: Here, assert that the node type is indeed T
// ?? Might be allocation failure, not T
return static_cast<T*>(TreePool::sharedPool()->node(m_identifier));
}
TreeNode * uncastedNode() const {
return TreePool::sharedPool()->node(m_identifier);
}
int identifier() const { return m_identifier; }
// Hierarchy
@@ -78,7 +84,7 @@ public:
// Hierarchy operations
void addChild(TreeReference<TreeNode> t) {
void addTreeChild(TreeReference<TreeNode> t) {
t.node()->retain();
TreePool::sharedPool()->move(t.node(), node()->next());
node()->incrementNumberOfChildren();
@@ -90,10 +96,12 @@ public:
}
void replaceWith(TreeReference<TreeNode> t) {
parent().replaceChild(node()->indexOfChild(t.node()), t);
TreeReference<T> p = parent();
p.replaceChildAtIndex(p.node()->indexOfChildByIdentifier(identifier()), t);
}
void replaceChildAtIndex(int oldChildIndex, TreeReference<TreeNode> newChild) {
// TODO decrement the children count of the new child parent
assert(oldChildIndex >= 0 && oldChildIndex < numberOfChildren());
TreeReference<T> oldChild = treeChildAtIndex(oldChildIndex);
TreePool::sharedPool()->move(newChild.node(), oldChild.node()->next());