mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-24 00:00:44 +01:00
Use operator new/delete directly on ExpressionNode
This commit is contained in:
2
Makefile
2
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)
|
||||
|
||||
@@ -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<AdditionNode> {
|
||||
public:
|
||||
Addition(Expression e1, Expression e2) :
|
||||
ExpressionReference<AdditionNode>()
|
||||
{
|
||||
// Ok, here I want to take e1 and e2 as operands
|
||||
ExpressionReference<EndNode> end;
|
||||
ExpressionNode::Pool()->log();
|
||||
addOperand(end);
|
||||
ExpressionNode::Pool()->log();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
25
end_node.h
Normal file
25
end_node.h
Normal file
@@ -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<EndNode> End;
|
||||
|
||||
#endif
|
||||
@@ -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;
|
||||
*/
|
||||
|
||||
@@ -22,6 +22,10 @@ public:
|
||||
return *(reinterpret_cast<const ExpressionReference<ExpressionNode> *>(this));
|
||||
}
|
||||
|
||||
void addOperand(ExpressionReference<ExpressionNode> e) {
|
||||
TreeReference<T>::addChild(e);
|
||||
}
|
||||
|
||||
float approximate() const {
|
||||
return this->node()->approximate();
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
119
test.cpp
119
test.cpp
@@ -2,31 +2,43 @@
|
||||
#include "addition_node.h"
|
||||
#include <stdio.h>
|
||||
|
||||
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<uint32_t *>(source);
|
||||
uint32_t * dst = reinterpret_cast<uint32_t *>(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
|
||||
|
||||
16
tree_node.cpp
Normal file
16
tree_node.cpp
Normal file
@@ -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();
|
||||
}
|
||||
}
|
||||
29
tree_node.h
29
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() {
|
||||
|
||||
@@ -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<TreeNode *>(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<char *>(ptr) - size,
|
||||
static_cast<char *>(ptr) + size,
|
||||
m_cursor - static_cast<char *>(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<uint32_t *>(source);
|
||||
uint32_t * dst = reinterpret_cast<uint32_t *>(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<char *>(source), reinterpret_cast<char *>(destination), source->deepSize());
|
||||
}
|
||||
|
||||
#if TREE_LOGGING
|
||||
#include <stdio.h>
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
68
tree_pool.h
68
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<TreeNode *>(const_cast<char *>(m_buffer)); }
|
||||
TreeNode * last() const { return reinterpret_cast<TreeNode *>(const_cast<char *>(m_cursor)); }
|
||||
|
||||
TreeNode * deepCopy(TreeNode * node) {
|
||||
size_t size = node->deepSize();
|
||||
void * ptr = alloc(size);
|
||||
memcpy(ptr, static_cast<void *>(node), size);
|
||||
TreeNode * copy = reinterpret_cast<TreeNode *>(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<TreeNode *>(const_cast<char *>(m_buffer))); }
|
||||
TreeNode::DepthFirst::Iterator end() const { return TreeNode::DepthFirst::Iterator(reinterpret_cast<TreeNode *>(const_cast<char *>(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
|
||||
|
||||
@@ -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<T*>(node)->~T();
|
||||
m_pool->dealloc(node, deepNodeSize);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
operator TreeReference<TreeNode>() const {
|
||||
// TODO: make sure this is kosher
|
||||
// static_assert(sizeof(ExpressionReference<T>) == sizeof(ExpressionReference<ExpressionNode>), "All ExpressionReference are supposed to have the same size");
|
||||
return *(reinterpret_cast<const TreeReference<TreeNode> *>(this));
|
||||
}
|
||||
|
||||
int numberOfChildren() const {
|
||||
@@ -44,32 +60,37 @@ public:
|
||||
return TreeReference(node()->childAtIndex(i));
|
||||
}
|
||||
|
||||
void addOperand(TreeReference<TreeNode> t) {
|
||||
assert(t.m_pool == m_pool);
|
||||
/*
|
||||
void addChild(TreeReference<TreeNode> 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<TreeNode> 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<T*>(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),
|
||||
|
||||
Reference in New Issue
Block a user