mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-30 04:00:02 +02:00
Merge Tree branch
This commit is contained in:
148
apps/tree/tree_pool.cpp
Normal file
148
apps/tree/tree_pool.cpp
Normal file
@@ -0,0 +1,148 @@
|
||||
#include "tree_pool.h"
|
||||
#include <string.h>
|
||||
|
||||
TreePool * TreePool::sharedPool() {
|
||||
static TreePool pool;
|
||||
return &pool;
|
||||
}
|
||||
|
||||
TreeNode * TreePool::node(int identifier) const {
|
||||
if (identifier < 0) {
|
||||
int index = indexOfStaticNode(identifier);
|
||||
assert(index >= 0 && index < MaxNumberOfStaticNodes);
|
||||
return m_staticNodes[index];
|
||||
}
|
||||
assert(identifier >= 0 && identifier <= MaxNumberOfNodes);
|
||||
return m_nodeForIdentifier[identifier];
|
||||
}
|
||||
|
||||
static void memmove32(uint32_t * dst, uint32_t * src, size_t len) {
|
||||
if (dst > src) {
|
||||
src += len;
|
||||
dst += len;
|
||||
while (len--) {
|
||||
*--dst = *--src;
|
||||
}
|
||||
} else {
|
||||
while (len--) {
|
||||
*dst++ = *src++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TreePool::logNodeForIdentifierArray() {
|
||||
printf("\n\n");
|
||||
for (int i = 0; i < MaxNumberOfNodes; i++) {
|
||||
if (m_nodeForIdentifier[i] != nullptr) {
|
||||
printf("Identifier %d, node %p\n", i, m_nodeForIdentifier[i]);
|
||||
}
|
||||
}
|
||||
printf("\n\n");
|
||||
}
|
||||
|
||||
void TreePool::move(TreeNode * source, TreeNode * destination) {
|
||||
size_t moveSize = source->deepSize();
|
||||
moveNodes(source, destination, moveSize);
|
||||
}
|
||||
|
||||
void TreePool::moveChildren(TreeNode * sourceParent, TreeNode * destination) {
|
||||
size_t moveSize = sourceParent->deepSize() - sourceParent->size();
|
||||
moveNodes(sourceParent->next(), destination, moveSize);
|
||||
}
|
||||
|
||||
void TreePool::moveNodes(TreeNode * source, TreeNode * destination, size_t moveSize) {
|
||||
if (source == destination || moveSize == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
char * destinationAddress = reinterpret_cast<char *>(destination);
|
||||
char * sourceAddress = reinterpret_cast<char *>(source);
|
||||
if (insert(destinationAddress, sourceAddress, moveSize)) {
|
||||
// Update the nodeForIdentifier array
|
||||
for (int i = 0; i < MaxNumberOfNodes; i++) {
|
||||
char * nodeAddress = reinterpret_cast<char *>(m_nodeForIdentifier[i]);
|
||||
if (nodeAddress == nullptr) {
|
||||
continue;
|
||||
} else if (nodeAddress >= sourceAddress && nodeAddress < sourceAddress + moveSize) {
|
||||
if (destinationAddress < sourceAddress) {
|
||||
m_nodeForIdentifier[i] = reinterpret_cast<TreeNode *>(nodeAddress - (sourceAddress - destinationAddress));
|
||||
} else {
|
||||
m_nodeForIdentifier[i] = reinterpret_cast<TreeNode *>(nodeAddress + (destinationAddress - (sourceAddress + moveSize)));
|
||||
}
|
||||
} else if (nodeAddress > sourceAddress && nodeAddress < destinationAddress) {
|
||||
m_nodeForIdentifier[i] = reinterpret_cast<TreeNode *>(nodeAddress - moveSize);
|
||||
} else if (nodeAddress < sourceAddress && nodeAddress >= destinationAddress) {
|
||||
m_nodeForIdentifier[i] = reinterpret_cast<TreeNode *>(nodeAddress + moveSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
void TreePool::log() {
|
||||
printf("POOL:");
|
||||
for (TreeNode * node : *this) {
|
||||
printf("|(%03d|%s|%03d|%p)", node->m_identifier, node->description(), node->retainCount(), node);
|
||||
}
|
||||
printf("|\n");
|
||||
|
||||
//logNodeForIdentifierArray();
|
||||
}
|
||||
|
||||
void * TreePool::alloc(size_t size) {
|
||||
if (m_cursor >= m_buffer + BufferSize || m_cursor + size > m_buffer + BufferSize) {
|
||||
return nullptr;
|
||||
}
|
||||
void * result = m_cursor;
|
||||
m_cursor += size;
|
||||
return result;
|
||||
}
|
||||
|
||||
void TreePool::dealloc(TreeNode * node) {
|
||||
char * ptr = reinterpret_cast<char *>(node);
|
||||
assert(ptr >= m_buffer && ptr < m_cursor);
|
||||
size_t size = node->size();
|
||||
|
||||
// Step 1 - Compact the pool
|
||||
memmove(
|
||||
ptr,
|
||||
ptr + size,
|
||||
m_cursor - (ptr + size)
|
||||
);
|
||||
m_cursor -= size;
|
||||
|
||||
// Step 2 - Update m_nodeForIdentifier
|
||||
for (int i = 0; i < MaxNumberOfNodes; i++) {
|
||||
if (m_nodeForIdentifier[i] != nullptr && m_nodeForIdentifier[i] > node) {
|
||||
m_nodeForIdentifier[i] = reinterpret_cast<TreeNode *>(reinterpret_cast<char *>(m_nodeForIdentifier[i]) - size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool TreePool::insert(char * destination, char * source, size_t length) {
|
||||
if (source == destination || (destination > source && destination < source + length)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
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;
|
||||
char tempBuffer[BufferSize];
|
||||
uint32_t * tmp = reinterpret_cast<uint32_t *>(tempBuffer);
|
||||
memmove32(reinterpret_cast<uint32_t *>(tmp), src, len);
|
||||
if (dst < src) {
|
||||
memmove32(dst + len, dst, src - dst);
|
||||
memmove32(dst, tmp, len);
|
||||
} else {
|
||||
memmove32(src, src + len, dst - (src + len));
|
||||
memmove32(dst - len, tmp, len);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
Reference in New Issue
Block a user