open-source-search-engine/MemPoolTree.h
2013-08-02 13:12:24 -07:00

139 lines
4.2 KiB
C++

// Matt Wells, Copyright, Apr 2001
// like RdbTree but custom for MemPool.h
#ifndef _MEMPOOLTREE_H_
#define _MEMPOOLTREE_H_
#include "Mem.h" // for g_mem.calloc and g_mem.malloc
class MemKey : public key_t {
public:
// . bitmap of "size" key needed by MemPool::malloc()
// . 1U000000 00000000 00000000 00000000 U = in use?
// . ssssssss ssssssss ssssssss ssssssss s = size
// . ffffffff ffffffff ffffffff ffffffff f = ptr into m_mem
void setSizeKey ( long size , void *ptr , bool inUse ) {
if ( inUse ) n1 = 0xc0000000;
else n1 = 0x80000000;
// least significant long comes first
*(((long *)&n0)+0) = (long) ptr;
*(((long *)&n0)+1) = (long) size;};
// . bitmap of "offset" key needed by MemPool::free()
// . 0U000000 00000000 00000000 00000000 U = in use?
// . ffffffff ffffffff ffffffff ffffffff f = ptr into m_mem
// . ssssssss ssssssss ssssssss ssssssss s = size
void setOffsetKey ( void *ptr , long size , bool inUse ) {
if ( inUse ) n1 = 0x40000000;
else n1 = 0;
// least significant long comes first
*(((long *)&n0)+0) = (long) size;
*(((long *)&n0)+1) = (long) ptr; };
bool inUse () { if (n1 & 0x40000000) return true; return false;};
bool isSizeKey () { if (n1 & 0x80000000) return true; return false;};
long getSize () {
if ( isSizeKey() ) return n0 >> 32;
else return n0 & 0xffffffff; };
char *getOffset () {
if ( isSizeKey() ) return (char *)(long)(n0 & 0xffffffff);
else return (char *)(long)(n0 >> 32); };
void setInUse ( bool inuse ) {
if ( inuse ) n1 = 0x40000000;
else n1 = 0;
};
};
// TODO: go back to using longs instead of MemNodes in case we get
// 64bit ptrs, we'd use double the ram!!
class MemNode {
public:
MemKey m_key;
class MemNode *m_left;
class MemNode *m_right;
class MemNode *m_parent;
char m_depth;
};
class MemPoolTree {
public:
// these alloc and free m_mem
MemPoolTree ( );
~MemPoolTree ( );
// . pass in the chunk of memory we'll use
// . we grow our MemNode array from top down, like a stack
bool init ( char *mem , long memSize );
// returns -1 and sets errno on error
MemNode *addNode ( MemKey &key );
// returns NULL if not found
MemNode *getNode ( MemKey &key );
// . get the node whose key is >= key
// . much much slower than getNextNode() below
MemNode *getNextNode ( MemKey &key );
MemNode *getNextNode ( MemNode *node );
// . get the node whose key is <= "key"
MemNode *getPrevNode ( MemKey &key );
MemNode *getPrevNode ( MemNode *node );
void deleteNode ( MemNode *node ) ;
void deleteNode ( MemKey &key ) {
MemNode *i = getNode ( key ); deleteNode(i); };
// get # of available nodes that are above m_floor
long getNumEmptyNodesAboveFloor ( ) {
return (long)((MemNode *)(m_mem+m_memSize) - m_floor) -
m_numUsedNodes; };
char *getFloor () { return (char *)m_floor; };
MemNode *addSizeNode ( long size , void *ptr , bool occupied ) {
if ( size <= 0 ) return (MemNode *)0x7fffffff;
MemKey k; k.setSizeKey ( size , ptr , occupied ) ;
return addNode ( k ); };
MemNode *addOffsetNode ( void *ptr , long size , bool occupied ) {
if ( size <= 0 ) return (MemNode *)0x7fffffff;
MemKey k ; k.setOffsetKey ( ptr , size , occupied ) ;
return addNode ( k ); };
void deleteOffsetNode ( void *ptr , long size , bool occupied ) {
if ( size <= 0 ) return;
MemKey k ; k.setOffsetKey ( ptr , size , occupied ) ;
deleteNode ( k ); };
void deleteSizeNode ( long size , void *ptr , bool occupied ) {
if ( size <= 0 ) return;
MemKey k ; k.setSizeKey ( size , ptr , occupied ) ;
deleteNode ( k ); };
private:
void setDepths ( MemNode *bottomNode );
MemNode * rotateRight ( MemNode *pivotNode );
MemNode * rotateLeft ( MemNode *pivotNode );
char *m_mem;
long m_memSize;
// switch between picking left and right kids to replace deleted nodes
// in order to keep the tree more balanced
char m_pickRight;
// the node at the top of the tree
MemNode *m_headNode;
// how many are in use?
long m_numUsedNodes ;
// node of the next available/empty node
MemNode *m_nextNode;
// maximum node # that was ever used at some point in time
MemNode *m_floor;
};
#endif