jdunn%netscape.com 2318eebe99 Fix for AIX build bustage. Unfortunately the compiler requires that if
a class includes other classes, then the other classes must be defined
by the time the enclosing class is.  In this case nsDST includes
NodeArena, LeafNode & TwoNode and so therefore those classes must be
defined in nsDST.h.

r troy: Note, Troy didn't APPROVE of the fix (since it isn't pretty) but
        he has graciously allowed it in order to help AIX development.
        He did believe that it wouldn't hurt to put the change in.


git-svn-id: svn://10.0.0.236/trunk@53313 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-12 03:52:50 +00:00

221 lines
7.0 KiB
C++

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsDST_h___
#define nsDST_h___
#ifdef HAVE_MEMORY_H
#include <memory.h>
#endif
#include "nsError.h"
#ifdef NS_DEBUG
#include <stdio.h>
#endif
#include "plarena.h"
/**
* Function-like object used when enumerating the nodes of the DST
*/
class nsDSTNodeFunctor {
public:
virtual void operator() (void* aKey, void* aValue) = 0; // call operator
};
// Option flags for Search() member function
#define NS_DST_REMOVE_KEY_VALUE 0x0001
// nsresult error codes
#define NS_DST_KEY_NOT_THERE \
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_LAYOUT, 1)
#define NS_DST_VALUE_OVERWRITTEN \
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_LAYOUT, 2)
/**
* Digital search tree for doing a radix-search of pointer-based keys
*/
class nsDST {
public:
class NodeArena;
friend class NodeArena;
private:
class LeafNode;
class TwoNode;
friend class LeafNode;
friend class TwoNode;
public:
typedef unsigned long PtrBits;
// Memory arena pool used for fast allocation and deallocation of DST nodes.
// Maintains a free-list of freed objects.
// Node arenas can be shared across DST objects (they don't lock when allocating
// and freeing memory, so don't share them across threads). The DST object(s)
// own the node arena, and you just hold a weak reference.
class NodeArena {
public:
NodeArena(PRUint32 aArenaSize);
~NodeArena();
// Memory management functions
void* AllocLeafNode();
void* AllocTwoNode();
void FreeNode(LeafNode*);
void FreeNode(TwoNode*);
void FreeArenaPool();
// Lifetime management functions
void AddRef() {mRefCnt++;}
void Release();
PRBool IsShared() const {return mRefCnt > 1;}
#ifdef NS_DEBUG
int NumArenas() const;
PRUint32 ArenaSize() const {return mPool.arenasize;}
#endif
private:
PLArenaPool mPool;
LeafNode* mLeafNodeFreeList;
TwoNode* mTwoNodeFreeList;
PRUint32 mRefCnt;
};
// Create a DST. You specify the node arena to use; this allows the arena to
// be shared.
// By ignoring low-order pointer bits that are always 0, the tree height can
// be reduced. Because pointer memory should be at least 32-bit aligned, the
// default is for level 0 of the tree to start with bit 0x04 (i.e., we ignore
// the two low-order bits)
nsDST(NodeArena* aArena, PtrBits aLevelZeroBit = 0x04);
~nsDST();
nsresult Search(void* aKey, unsigned aOptions, void** aValue);
nsresult Insert(void* aKey, void* aValue, void** aOldValue);
nsresult Remove(void* aKey);
nsresult Clear();
nsresult Enumerate(nsDSTNodeFunctor& aFunctor) const;
#ifdef NS_DEBUG
void Dump(FILE*) const;
#endif
// Create a memory arena pool. You can specify the size of the underlying arenas
static NodeArena* NewMemoryArena(PRUint32 aArenaSize = 512);
private:
/////////////////////////////////////////////////////////////////////////////
// Classes that represents nodes in the DST
// To reduce the amount of memory we use there are two types of nodes:
// - leaf nodes
// - two nodes (left and right child)
//
// We distinguish the two types of nodes by looking at the low-order
// bit of the key. If it is 0, then the node is a leaf node. If it is
// 1, then the node is a two node. Use function Key() when retrieving
// the key, and function IsLeaf() to tell what type of node it is
//
// It's an invariant of the tree that a two node can not have both child links
// NULL. In that case it must be converted back to a leaf node
//
// NOTE: This code was originally put into nsDST.cpp to reduce size
// and to hide the implementation - See Troy's 1.10 revision.
// However the AIX xlC 3.6.4.0 compiler does not allow this.
class LeafNode {
public:
void* mKey;
void* mValue;
// Constructors
LeafNode(void* aKey, void* aValue);
LeafNode(const LeafNode& aLeafNode);
// Accessor for getting the key. Clears the bit used to tell if the
// node is a leaf. This function can be safely used on any node without
// knowing whether it's a leaf or a two node
void* Key() const {return (void*)(PtrBits(mKey) & ~0x1);}
// Helper function that returns TRUE if the node is a leaf
int IsLeaf() const {return 0 == (PtrBits(mKey) & 0x1);}
// Overloaded placement operator for allocating from an arena
void* operator new(size_t aSize, NodeArena* aArena) {return aArena->AllocLeafNode();}
};
// Definition of TwoNode class
class TwoNode : public LeafNode {
public:
LeafNode* mLeft; // left subtree
LeafNode* mRight; // right subtree
TwoNode(const LeafNode& aLeafNode);
void SetKeyAndValue(void* aKey, void* aValue) {
mKey = (void*)(PtrBits(aKey) | 0x01);
mValue = aValue;
}
// Overloaded placement operator for allocating from an arena
void* operator new(size_t aSize, NodeArena* aArena) {return aArena->AllocTwoNode();}
private:
TwoNode(const TwoNode&); // no implementation
void operator=(const TwoNode&); // no implementation
};
LeafNode* mRoot; // root node of the tree
NodeArena* mArena;
PtrBits mLevelZeroBit;
private:
// Helper functions
LeafNode* RemoveLeftMostLeafNode(TwoNode** aTwoNode);
void DestroyNode(LeafNode* aLeafNode);
void DestroyNode(TwoNode* aTwoNode);
LeafNode* ConvertToLeafNode(TwoNode** aTwoNode);
TwoNode* ConvertToTwoNode(LeafNode** aLeafNode);
void EnumTree(LeafNode* aNode, nsDSTNodeFunctor& aFunctor) const;
void FreeTree(LeafNode* aNode);
nsresult SearchTree(void* aKey, unsigned aOptions, void** aValue);
#ifdef NS_DEBUG
// Diagnostic functions
void VerifyTree(LeafNode* aNode, int aLevel = 0, PtrBits aLevelKeyBits = 0) const;
LeafNode* DepthFirstSearch(LeafNode* aNode, void* aKey) const;
void GatherStatistics(LeafNode* aNode,
int aLevel,
int& aNumLeafNodes,
int& aNumTwoNodes,
int aNodesPerLevel[]) const;
#endif
nsDST(const nsDST&); // no implementation
void operator=(const nsDST&); // no implementation
};
#endif /* nsDST_h___ */