wcsbase.mh

来自「开放源码的编译器open watcom 1.6.0版的源代码」· MH 代码 · 共 546 行 · 第 1/2 页

MH
546
字号
//
//  wcsbase.h    Definitions and base implementation for the WATCOM Container
//               Skip List class
//
:keep CPP_HDR
:include crwat.sp
//
#ifndef _WCSBASE_H_INCLUDED
#define _WCSBASE_H_INCLUDED
:include readonly.sp

#ifndef __cplusplus
#error wcsbase.h is for use with C++
#endif

#ifndef _STDDEF_H_INCLUDED
 #include <stddef.h>
#endif

:include undefnew.sp

//
// Skip Lists are a probabilistic alternative to balanced trees, as
// described in the June 1990 issue of CACM and were invented by
// William Pugh in 1987.
//

//
// constants
//

//
// The probability one more pointer being added to a skip list node
// one quarter and one half.  One of these constants may be passed to
// constructor as the optional prob parameter, WCSKIPLIST_PROB_QUARTER
// is used by default.
//

const unsigned WCSKIPLIST_PROB_QUARTER = 3;
const unsigned WCSKIPLIST_PROB_HALF = 1;

//
// The default maximum number of pointers in each node.  This is used as
// a default value for the max_ptrs constructor parameter.  The default
// prob and max_ptrs constructor parameters are suitable for skip lists
// with upto about 100,000 elements.
//

const unsigned WCDEFAULT_SKIPLIST_MAX_PTRS = 8;

//
// The maximum value for the max_ptrs constructor parameter.  If a value
// greater than WCSKIPLIST_MAX_PTRS is passed to the max_ptrs constructor
// parameter, then WCSKIPLIST_MAX_PTRS will be used as the maximum number
// of pointers.  With WCSKIPLIST_PROB_QUARTER, WCSKIPLIST_MAX_POINTERS is
// suitable for a skip list containing over four billion elements.  With
// WCSKIPLIST_PROB_HALF, WCSKIPLIST_MAX_POINTERS is suitable for a skip
// list containing over one million elements.
//

const unsigned WCSKIPLIST_MAX_PTRS = 20;



//
// WCSkipListPtrs and WCSkipListNode are used internally by the SkipList
// classes to store an element and its pointers into the skip list.
//

struct WCSkipListPtrs {
    WCSkipListPtrs *forward[ 1 ];       // variable sized array of forward ptrs
};

template <class Type>
class WCSkipListNode {
public:
    Type data;
    WCSkipListPtrs ptrs;

    inline void * operator new( size_t, void * ptr ){
        return ptr;
    }

    inline WCSkipListNode( const Type &elem ) : data( elem ) {};
    inline ~WCSkipListNode() {};
};



//
// Skip List Dictionary implementation object:
// Combines the Key and Value into one object (used internally)
//

template <class Key, class Value>
class WCSkipListDictKeyVal{
public:
    Key key;
    Value value;

    inline WCSkipListDictKeyVal( const WCSkipListDictKeyVal &orig )
            : key( orig.key ), value( orig.value ) {};
    inline WCSkipListDictKeyVal( const Key &new_key, const Value &new_value )
            : key( new_key ), value( new_value ) {};
    inline WCSkipListDictKeyVal( const Key &new_key ) : key( new_key ) {};
    inline WCSkipListDictKeyVal() {};
    inline ~WCSkipListDictKeyVal() {};
};


// Macros to give the user the size of allocated objects
#define WCValSkipListItemSize( Type, num_ptrs )                         \
    ( sizeof( WCSkipListNode<Type> ) + ( num_ptrs - 1 ) * sizeof( void * ) )
#define WCPtrSkipListItemSize( Type, num_ptrs )                         \
    WCValSkipListItemSize( void *, num_ptrs )
#define WCValSkipListSetItemSize( Type, num_ptrs )                      \
    WCValSkipListItemSize( Type, num_ptrs )
#define WCPtrSkipListSetItemSize( Type, num_ptrs )                      \
    WCPtrSkipListItemSize( Type, num_ptrs )
#define WCValSkipListDictItemSize( Key, Value, num_ptrs )               \
    ( sizeof( WCSkipListNode<WCSkipListDictKeyVal<Key, Value> > )       \
      + ( num_ptrs - 1 ) * sizeof( void * ) )
#define WCPtrSkipListDictItemSize( Key, Value, num_ptrs )               \
    WCValSkipListDictItemSize( void *, void *, num_ptrs )



//
// This base class provides skip list base functionality which does not
// require the templated Type.
//
// WCExcept is a base class to provide exception handling.
//
// This is an abstract class to prevent objects of this type being created.
//

class WCSkipNonTempBase : public WCExcept {
private:
    // raw memory for the header element pointers
    char header_mem[ sizeof( void * ) * WCSKIPLIST_MAX_PTRS ];
    // if FALSE, insert will not insert a duplicate value
    const WCbool allowDuplicates;

    void base_init( unsigned prob, unsigned max_ptrs );

protected:
    // user allocator and deallocator functions
    void * (* alloc_fn)( size_t );
    void (* dealloc_fn)( void *, size_t );

    // for base_random_level
    _WPRTLINK static unsigned randomsLeft;
    _WPRTLINK static unsigned randomBits;
    unsigned max_ptrs_in_node;
    unsigned probability;

    // the current greatest level of elements in the list
    // (1 more than the number of levels in the list)
    int level;
    // a pointer to the header link in the skip list
    // (points to initialized header_mem)
    WCSkipListPtrs *header;
    unsigned num_entries;


    // pointer to the nodes stored in the skiplist
    typedef WCSkipListPtrs* node_ptr;

    // non-templated pointers to the templated Type
    typedef const void *TTypePtr;


    // true if elements are equivalence
    virtual int base_equiv( node_ptr elem1, TTypePtr elem2 ) const = 0;

    // true if lhs < rhs
    virtual int base_less( node_ptr lhs, TTypePtr rhs ) const = 0;

    // equivalents of new and delete
    virtual node_ptr base_new_node( TTypePtr elem
                                  , unsigned level_less_1 ) = 0;

    virtual void base_delete_node( node_ptr node, unsigned level_less_1 ) = 0;

    // the assignment operator base
    _WPRTLINK void base_assign( const WCSkipNonTempBase * orig );

    // the copy constructor base
    _WPRTLINK void base_construct( const WCSkipNonTempBase * orig );

    _WPRTLINK node_ptr base_find( TTypePtr elem ) const;

    _WPRTLINK node_ptr base_find_with_update( TTypePtr elem,
                                             node_ptr update[] ) const;

// this should be private eventually
    inline void base_init_header() {
        header = (node_ptr)header_mem;
        for( int i = 0; i < max_ptrs_in_node; i++ ){
            header->forward[ i ] = 0;
        }
    };

    _WPRTLINK node_ptr base_insert( TTypePtr elem );

    // insert a copy of the data contained in this node
    // (used by base_construct)
    virtual int base_insert_copy( node_ptr ) = 0;

    // for WCSkipListDuplicatesBase
    _WPRTLINK unsigned base_occurrencesOf( TTypePtr elem ) const;

    _WPRTLINK int base_random_level();

    // for WCSkipListDuplicatesBase
    _WPRTLINK unsigned base_removeAll( TTypePtr elem );

    _WPRTLINK node_ptr base_remove_but_not_delete( TTypePtr elem,
                                                  int &num_ptrs );

public:
    _WPRTLINK WCSkipNonTempBase( unsigned prob, unsigned max_ptrs
                     , WCbool duplicates );

    _WPRTLINK WCSkipNonTempBase( unsigned prob, unsigned max_ptrs
                     , void * (*user_alloc)( size_t )
                     , void (*user_dealloc)( void *, size_t )
                     , WCbool duplicates );

    inline virtual ~WCSkipNonTempBase() {};

    _WPRTLINK void clear();

    _WPRTLINK WCbool remove( TTypePtr elem );
};




//
// WCSkipListBase provides the skip list functionality
//
// This is an abstract class to prevent objects of this type being created.
//

template<class Type>
class WCSkipListBase : public WCSkipNonTempBase {
protected:
    // the nodes stored in the skip list
    typedef WCSkipListNode<Type> NodeType;


    inline node_ptr base_find( const Type &elem ) const {
        return( WCSkipNonTempBase::base_find( &elem ) );
    };

    // given a node_ptr (which points to the forward pointers in a node),
    // return a pointer to the whole node (WCSkipListNode<Type>)
    // this WILL NOT WORK if sizeof( char ) != 1
    static inline WCSkipListNode<Type> *base_whole_node( node_ptr node_ptrs ) {
        return( (NodeType *)( (char *)node_ptrs
                            - offsetof( NodeType, ptrs ) ) );
    };

    inline node_ptr base_insert( const Type &elem ) {
        return( WCSkipNonTempBase::base_insert( &elem ) );
    }

    // insert a copy of the data contained in node
    virtual int base_insert_copy( node_ptr node ) {
        return( base_insert( base_whole_node( node )->data ) != 0 );
    };

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?