From 68f663d47ebaa48522fc5e7a3f2598a0b05d0a8f Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Tue, 12 Jun 2018 16:50:49 +0200 Subject: [PATCH] Use operator new/delete directly on ExpressionNode --- Makefile | 2 +- addition_node.h | 9 +++- end_node.h | 25 +++++++++ expression_node.h | 23 ++++++-- expression_reference.h | 4 ++ float_node.h | 2 +- test.cpp | 119 +++++++++++------------------------------ tree_node.cpp | 16 ++++++ tree_node.h | 29 ++++++++-- tree_pool.cpp | 48 +++++++++++++++-- tree_pool.h | 68 ++++++++--------------- tree_reference.h | 53 ++++++++++++------ 12 files changed, 234 insertions(+), 164 deletions(-) create mode 100644 end_node.h create mode 100644 tree_node.cpp diff --git a/Makefile b/Makefile index 992202f4f..e2ef28479 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -OBJS = tree_pool.o tree_reference.o test.o +OBJS = tree_pool.o tree_node.o tree_reference.o test.o CXXFLAGS = -std=c++11 -g -O0 test: $(OBJS) diff --git a/addition_node.h b/addition_node.h index b7c427f9e..e559e7a34 100644 --- a/addition_node.h +++ b/addition_node.h @@ -6,7 +6,7 @@ class AdditionNode : public ExpressionNode { public: - AdditionNode(int identifier) : ExpressionNode(identifier) { + AdditionNode() : ExpressionNode() { printf("Create Addition\n"); } #if TREE_LOGGING @@ -31,12 +31,17 @@ public: */ }; +#include "end_node.h" + class Addition : public ExpressionReference { public: Addition(Expression e1, Expression e2) : ExpressionReference() { - // Ok, here I want to take e1 and e2 as operands + ExpressionReference end; + ExpressionNode::Pool()->log(); + addOperand(end); + ExpressionNode::Pool()->log(); } }; diff --git a/end_node.h b/end_node.h new file mode 100644 index 000000000..e454765c1 --- /dev/null +++ b/end_node.h @@ -0,0 +1,25 @@ +#ifndef END_NODE_H +#define END_NODE_H + +#include "expression_reference.h" +#include "expression_node.h" + +class EndNode : public ExpressionNode { +public: + EndNode() : ExpressionNode() { + printf("Create end node\n"); + } + float approximate() override { + assert(false); + return 0.0f; + } +#if TREE_LOGGING + const char * description() const override { + return "End"; + } +#endif +}; + +//typedef ExpressionReference End; + +#endif diff --git a/expression_node.h b/expression_node.h index eeeb6c439..03d05ad71 100644 --- a/expression_node.h +++ b/expression_node.h @@ -2,12 +2,23 @@ #define EXPRESSION_NODE_H #include "tree_node.h" - -class TreePool; +#include "tree_pool.h" class ExpressionNode : public TreeNode { public: - ExpressionNode(int identifier) : TreeNode(identifier) {} + ExpressionNode() : TreeNode(Pool()->generateIdentifier()) {} + + // TODO: operator new and delte + // this behavior is the same for every TreeNode + // Find a way to define it on the TreeNode + + void * operator new(size_t count) { + return Pool()->alloc(count); + } + + void operator delete(void * ptr) { + Pool()->dealloc(ptr); + } static TreePool * Pool() { static TreePool pool; @@ -20,3 +31,9 @@ public: }; #endif + +/* Code I want to write: + * + * ExpressionNode * n = new AdditionNode(); + * delete n; + */ diff --git a/expression_reference.h b/expression_reference.h index b851a67d4..9b6e93e24 100644 --- a/expression_reference.h +++ b/expression_reference.h @@ -22,6 +22,10 @@ public: return *(reinterpret_cast *>(this)); } + void addOperand(ExpressionReference e) { + TreeReference::addChild(e); + } + float approximate() const { return this->node()->approximate(); } diff --git a/float_node.h b/float_node.h index 6aae43a7f..843de0ee0 100644 --- a/float_node.h +++ b/float_node.h @@ -6,7 +6,7 @@ class FloatNode : public ExpressionNode { public: - FloatNode(int identifier) : ExpressionNode(identifier) { + FloatNode() : ExpressionNode() { printf("Create float\n"); } size_t size() const override { diff --git a/test.cpp b/test.cpp index 23ebf14f3..7a643d9bd 100644 --- a/test.cpp +++ b/test.cpp @@ -2,31 +2,43 @@ #include "addition_node.h" #include +void poolTest() { + ExpressionNode::Pool()->log(); + + FloatNode * f = new FloatNode(); + f->setFloat(0.1f); + + FloatNode * g = new FloatNode(); + g->setFloat(1.1f); + + AdditionNode * h = new AdditionNode(); + + EndNode * i = new EndNode(); + + ExpressionNode::Pool()->log(); + + delete g; + + ExpressionNode::Pool()->log(); +} + +Expression buildAddition() { + Float smallFloat(0.2f); + Float bigFloat(3.4f); + + ExpressionNode::Pool()->log(); + + Addition a(smallFloat, bigFloat); + + ExpressionNode::Pool()->log(); + return a; +} int main() { printf("Hello\n"); + buildAddition(); - ExpressionNode::Pool()->log(); - Float e(0.2f); - - ExpressionNode::Pool()->log(); - - if (true) { - Expression j = e; - - ExpressionNode::Pool()->log(); - - Float m(3.4f); - - ExpressionNode::Pool()->log(); - } - - ExpressionNode::Pool()->log(); - - Addition a(e, e); - - ExpressionNode::Pool()->log(); /* Expression e = Parse("1+1"); @@ -34,74 +46,7 @@ int main() { Expression f = Addition(e, Parse("5")); f.removeChildAtIndex(0); */ -#if 0 - TreeNodePool pool; - TreeNodePool * p = &pool; - pool.log(); - - TreeNode * t1 = new (pool) AdditionNode(); - - TreeNode * t1 = TreeNode::Create(p, 11); - TreeNode * t2 = TreeNode::Create(p, 12); - TreeNode * t3 = TreeNode::Create(p, 13); - - TreeNode * t4 = AddNode::Create(t1, t3); - //TreeNode * t4 = new(p) IntNode(4); - // - t4->createChild(Addition() - - pool.log(); - - pool.move(t1, t3); - - pool.log(); -#endif return 0; } - - -#if 0 - -static inline swap(uint32_t * a, uint32_t * b) { - uint32_t tmp = *a; - *a = *b; - *b = tmp; -} - -void insert(char * source, char * destination, size_t length) { - assert(length % 4 == 0); - assert(source % 4 == 0); - assert(destination % 4 == 0); - uint32_t * src = reinterpret_cast(source); - uint32_t * dst = reinterpret_cast(destination); - size_t len = length/4; - - if (dst < src) { - if (src - dst <= len) { - uint32_t * srcPointer = src; - uint32_t * dstPointer = dst; - while (dstPointer != src) { - swap(srcPointer, dstPointer); - srcPointer++; - dstPointer++; - if (srcPointer == src + len) { - srcPointer = src; - } - } - } - } -} - -void TreeNodePool::move(TreeNode * source, TreeNode * destination) { - if (source == destination) { - return; - } - insert(source, destination, source->deepSize()); -} - -bool TreeNode::hasVariableNumberOfChildren() const { - return false; -} -#endif diff --git a/tree_node.cpp b/tree_node.cpp new file mode 100644 index 000000000..f5e69032f --- /dev/null +++ b/tree_node.cpp @@ -0,0 +1,16 @@ +#include "tree_node.h" +#include "expression_node.h" + +void TreeNode::release() { + m_referenceCounter--; + for (TreeNode * child : directChildren()) { + child->release(); + } + if (m_referenceCounter == 0) { + printf("DELETE %d(%p)\n", m_identifier, this); + delete this; + //dealloc(); + printf("Will log\n"); + ExpressionNode::Pool()->log(); + } +} diff --git a/tree_node.h b/tree_node.h index 7f9e50ef6..8034c120e 100644 --- a/tree_node.h +++ b/tree_node.h @@ -16,7 +16,6 @@ public: virtual ~TreeNode() { } - // Iterators class Iterator { @@ -28,6 +27,25 @@ public: TreeNode * m_node; }; + class Direct { + public: + Direct(TreeNode * node) : m_node(node) {} + class Iterator : public TreeNode::Iterator { + public: + using TreeNode::Iterator::Iterator; + Iterator & operator++() { + m_node = m_node->nextSibling(); + return *this; + } + }; + Iterator begin() const { return Iterator(m_node->next()); } + Iterator end() const { return Iterator(m_node->nextSibling()); } + private: + TreeNode * m_node; + }; + + Direct directChildren() { return Direct(this); } + class DepthFirst { public: DepthFirst(TreeNode * node) : m_node(node) {} @@ -35,7 +53,7 @@ public: public: using TreeNode::Iterator::Iterator; Iterator & operator++() { - printf(" Iterating from %d(%p) to %d(%p)\n", m_node->m_identifier, m_node, m_node->next()->m_identifier, m_node->next()); + // printf(" Iterating from %d(%p) to %d(%p)\n", m_node->m_identifier, m_node, m_node->next()->m_identifier, m_node->next()); m_node = m_node->next(); return *this; } @@ -64,8 +82,11 @@ public: void retain() { m_referenceCounter++; } - void release() { - m_referenceCounter--; + void release(); + + void rename(int identifier) { + m_identifier = identifier; + m_referenceCounter = 1; } int retainCount() { diff --git a/tree_pool.cpp b/tree_pool.cpp index af69c5494..c6c7479ec 100644 --- a/tree_pool.cpp +++ b/tree_pool.cpp @@ -8,11 +8,15 @@ void * TreePool::alloc(size_t size) { return result; } -void TreePool::dealloc(void * ptr, size_t size) { +void TreePool::dealloc(void * ptr) { + assert(ptr >= m_buffer && ptr < m_cursor); + TreeNode * node = reinterpret_cast(ptr); + size_t size = node->size(); + printf("Dealloc %d(%p) of size %d\n", node->m_identifier, node, size); // Step 1 - Compact the pool memmove( ptr, - static_cast(ptr) - size, + static_cast(ptr) + size, m_cursor - static_cast(ptr) ); m_cursor -= size; @@ -37,14 +41,50 @@ TreeNode * TreePool::node(int identifier) const { return nullptr; } +static inline void swap(uint32_t * a, uint32_t * b) { + uint32_t tmp = *a; + *a = *b; + *b = tmp; +} + +static inline void insert(char * source, char * destination, size_t length) { + assert(length % 4 == 0); + assert((long)source % 4 == 0); + assert((long)destination % 4 == 0); + uint32_t * src = reinterpret_cast(source); + uint32_t * dst = reinterpret_cast(destination); + size_t len = length/4; + + if (dst < src) { + if (src - dst <= len) { + uint32_t * srcPointer = src; + uint32_t * dstPointer = dst; + while (dstPointer != src) { + swap(srcPointer, dstPointer); + srcPointer++; + dstPointer++; + if (srcPointer == src + len) { + srcPointer = src; + } + } + } + } +} + +void TreePool::move(TreeNode * source, TreeNode * destination) { + if (source == destination) { + return; + } + insert(reinterpret_cast(source), reinterpret_cast(destination), source->deepSize()); +} + #if TREE_LOGGING #include void TreePool::log() { printf("POOL:"); for (TreeNode * node : *this) { - printf("|%d", node->m_identifier); - //printf("|(%03d|%s|%03d)", node->m_identifier, node->description(), node->retainCount()); + printf("|(%03d|%s|%03d|%p)", node->m_identifier, node->description(), node->retainCount(), node); } printf("|\n"); } diff --git a/tree_pool.h b/tree_pool.h index 196b861bf..63b68fedd 100644 --- a/tree_pool.h +++ b/tree_pool.h @@ -10,70 +10,46 @@ public: TreePool() : m_lastIdentifier(0), m_cursor(m_buffer) {} int generateIdentifier() { - assert(node(m_lastIdentifier) == nullptr); + /* For now we're not bothering with making sure the identifiers are indeed + * unique. We're just assuming we'll never overflow... */ + //assert(node(m_lastIdentifier) == nullptr); return m_lastIdentifier++; } void reclaimIdentifier(int identifier) { } void * alloc(size_t size); - void dealloc(void * ptr, size_t size); + void dealloc(void * ptr); TreeNode * node(int identifier) const; + void move(TreeNode * source, TreeNode * destination); + TreeNode * first() const { return reinterpret_cast(const_cast(m_buffer)); } + TreeNode * last() const { return reinterpret_cast(const_cast(m_cursor)); } + + TreeNode * deepCopy(TreeNode * node) { + size_t size = node->deepSize(); + void * ptr = alloc(size); + memcpy(ptr, static_cast(node), size); + TreeNode * copy = reinterpret_cast(ptr); + copy->rename(generateIdentifier()); + for (TreeNode * child : copy->depthFirstChildren()) { + child->rename(generateIdentifier()); + } + return copy; + } + #if TREE_LOGGING void log(); #endif private: - TreeNode::DepthFirst::Iterator begin() const { return TreeNode::DepthFirst::Iterator(reinterpret_cast(const_cast(m_buffer))); } - TreeNode::DepthFirst::Iterator end() const { return TreeNode::DepthFirst::Iterator(reinterpret_cast(const_cast(m_cursor))); } + TreeNode::DepthFirst::Iterator begin() const { return TreeNode::DepthFirst::Iterator(first()); } + TreeNode::DepthFirst::Iterator end() const { return TreeNode::DepthFirst::Iterator(last()); } int m_lastIdentifier; char * m_cursor; char m_buffer[256]; }; -#if 0 -class TreePool { -public: - TreePool() : - m_identifier(0), - m_cursor(m_data) - { - } - - class Slot { - public: - Slot(int identifier, void * area) : - m_identifier(identifier), m_area(area) {} - int identifier() const { return m_identifier; } - void * area() const { return m_area; } - private: - int m_identifier; - void * m_area; - int m_size; - }; - - Slot alloc(size_t size); - void dealloc(Slot s, size_t size); - - //TreeNode * node(int identifier) const; - TreeNode * alloc(size_t size) { - - } - void dealloc(TreeNode * node); - - void move(TreeNode * source, TreeNode * destination); -//#define TREE_LOGGING 1 -#if TREE_LOGGING - void log(); -#endif - private: - int m_identifier; - char * m_cursor; - char m_data[200]; -}; -#endif - #endif diff --git a/tree_reference.h b/tree_reference.h index a2c13f0c5..3a47f47f5 100644 --- a/tree_reference.h +++ b/tree_reference.h @@ -20,8 +20,17 @@ public: ~TreeReference() { TreeNode * node = this->node(); node->release(); +#if 0 if (node->retainCount() == 0) { + + + // Here we deal with removing a node. + // It's not as easy as one may think. + // -> When a node is not needed anymore + + printf("Discarding node %d(%p)\n", node->identifier(), node); + // Here the static_cast should fail if T is not a subclass of TreeNode size_t deepNodeSize = node->deepSize(); #if 0 @@ -34,6 +43,13 @@ public: static_cast(node)->~T(); m_pool->dealloc(node, deepNodeSize); } +#endif + } + + operator TreeReference() const { + // TODO: make sure this is kosher + // static_assert(sizeof(ExpressionReference) == sizeof(ExpressionReference), "All ExpressionReference are supposed to have the same size"); + return *(reinterpret_cast *>(this)); } int numberOfChildren() const { @@ -44,32 +60,37 @@ public: return TreeReference(node()->childAtIndex(i)); } - void addOperand(TreeReference t) { - assert(t.m_pool == m_pool); - /* + void addChild(TreeReference t) { + //assert(t.m_pool == m_pool); + //t.node()->retain(); + TreeNode * deepCopy = m_pool->deepCopy(t.node()); m_pool->move( - t->node(), - t->next() + deepCopy, + node()->next() ); - */ } -protected: - TreeReference(TreePool * pool) : - m_pool(pool) - { - int identifier = pool->generateIdentifier(); - void * area = pool->alloc(sizeof(T)); - TreeNode * n = new (area) T(identifier); - m_identifier = n->identifier(); - assert(m_identifier == identifier); - //m_cachedNode = n; + void removeChild(TreeReference t) { + m_pool->move( + t.node(), + m_pool->last() + ); + t.node()->release(); } T * node() const { // TODO: Here, assert that the node type is indeed T return static_cast(m_pool->node(m_identifier)); } + +protected: + TreeReference(TreePool * pool) : + m_pool(pool) + { + TreeNode * node = new T(); + m_identifier = node->identifier(); + } + private: TreeReference(TreePool * pool, TreeNode * node) : m_pool(pool),