mhoyt       2004/11/19 15:24:46

  Modified:    c/src/xalanc/Include XalanMap.hpp
  Log:
  Improved XalanMap implementation
  
  Revision  Changes    Path
  1.17      +144 -149  xml-xalan/c/src/xalanc/Include/XalanMap.hpp
  
  Index: XalanMap.hpp
  ===================================================================
  RCS file: /home/cvs/xml-xalan/c/src/xalanc/Include/XalanMap.hpp,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -r1.16 -r1.17
  --- XalanMap.hpp      8 Nov 2004 18:08:50 -0000       1.16
  +++ XalanMap.hpp      19 Nov 2004 23:24:46 -0000      1.17
  @@ -29,8 +29,6 @@
   #include <utility>
   
   
  -
  -
   #include <xalanc/Include/XalanVector.hpp>
   #include <xalanc/Include/XalanList.hpp>
   
  @@ -38,6 +36,11 @@
   
   XALAN_CPP_NAMESPACE_BEGIN
   
  +#if defined(_MSC_VER)
  +#pragma warning(push)
  +#pragma warning(disable: 4189)
  +#endif
  +
   typedef size_t       size_type;
   
   template <class Key>
  @@ -91,35 +94,6 @@
   /**
    * Xalan map entry pair of a key and data
    */
  -template <class KeyType,  class DataType>
  -struct XalanMapEntry
  -{
  -    typedef KeyType     first_type;
  -    typedef DataType    second_type;
  -
  -     typedef size_t  size_type;
  -     
  -    XalanMapEntry(
  -            const first_type & theFirst, 
  -            const second_type& theSecond,
  -            size_type index = 0) : 
  -             first(theFirst),
  -        second(theSecond),
  -        bucketIndex(index)
  -     {
  -     }
  -
  -     XalanMapEntry() : 
  -             first(),
  -        second(),
  -        bucketIndex(size_type())
  -     {
  -     }
  -
  -    first_type      first;
  -    second_type     second;
  -    size_type       bucketIndex;
  -};
   
   
   
  @@ -140,7 +114,7 @@
   };
   
   template <class XalanMapTraits, class BaseIterator>
  -struct XalanMapIterator : public BaseIterator
  +struct XalanMapIterator
   {
       typedef typename XalanMapTraits::value_type         value_type;
       typedef typename XalanMapTraits::reference          reference;
  @@ -151,45 +125,52 @@
   
       typedef XalanMapIterator<
                XalanMapIteratorTraits<value_type>, 
  -             typename BaseIterator::iterator>        Iterator; 
  -
  -    XalanMapIterator() :
  -            BaseIterator()
  -    {
  -    }
  +             BaseIterator>                                   Iterator; 
   
       XalanMapIterator(const Iterator & theRhs) :
  -            BaseIterator(theRhs)
  +        baseIterator(theRhs.baseIterator)
       {
       }
   
       XalanMapIterator(const BaseIterator & theRhs) :
  -            BaseIterator(theRhs)
  +        baseIterator(theRhs)
       {
       }
   
       XalanMapIterator operator++(int)
       {
  -      XalanMapIterator temp(*this);
  -      BaseIterator::operator++();
  -      return temp;
  +         XalanMapIterator temp(*this);
  +         ++baseIterator;
  +         return temp;
       }
   
       XalanMapIterator& operator++()
       {
  -      BaseIterator::operator++();
  -      return *this;
  +        ++baseIterator;
  +        return *this;
       }
   
       reference operator*() const
       {
  -        return *(BaseIterator::operator*());
  +        return *baseIterator->value;
       }
   
       pointer operator->() const
       {
  -        return (BaseIterator::operator*());
  +        return baseIterator->value;
  +    }
  +
  +    bool operator==(const XalanMapIterator& theRhs) const
  +    {
  +        return theRhs.baseIterator == baseIterator;
       }
  +
  +    bool operator!=(const XalanMapIterator& theRhs) const
  +    {
  +        return !(theRhs == *this);
  +    }
  +
  +    BaseIterator baseIterator;
   };
   
   
  @@ -206,26 +187,42 @@
   {
   public:
        /**
  -      * Each map entry is stored in a linked list.
  -      * The hash buckets are a vector of pointers into the entry list
  -      * An empty bucket will point to the end of the list,
  -      * A non-empty bucket will point to its first entry.  Remaining
  -      * entries in the chain follow the first and have the same index value.
  -      */
  +      * Each map entry is stored in a linked list where an entry
  +     * consists of a pointer to the key/value pair and a flag to indicate
  +     * whether the entry has been erased.
  +     * The hash buckets are a vector of pointers into the entry list.
  +     * Deleted entries are spliced into another list and marked 'erased'.
  +     */
   
        typedef Key                                     key_type;
        typedef Value                           data_type;
        typedef size_t                          size_type;
   
  -     typedef XalanMapEntry<const key_type, data_type>   value_type;
  -    typedef value_type  Entry;
  +     typedef XALAN_STD_QUALIFIER pair<const key_type, data_type>   
value_type;
   
  -     typedef XalanList<Entry*>                                               
                        EntryListType;
  +    struct Entry
  +    {
  +        value_type* value;
  +        bool        erased;
   
  -    typedef XalanMapIterator<XalanMapIteratorTraits<Entry>, typename 
EntryListType::iterator>            iterator;
  -    typedef XalanMapIterator<XalanMapConstIteratorTraits<Entry>, typename 
EntryListType::const_iterator> const_iterator;
  +        Entry(value_type* theValue) :
  +            value(theValue),
  +            erased(false)
  +        {
  +        }
  +    };
   
  -     typedef XalanVector<iterator>           EntryPosVectorType;
  +    typedef XalanList<Entry>                                EntryListType;
  +
  +    typedef XalanVector<typename EntryListType::iterator>    BucketType;
  +    typedef XalanVector<BucketType>                         BucketTableType;
  +
  +    typedef XalanMapIterator<
  +                XalanMapIteratorTraits<value_type>, 
  +                typename EntryListType::iterator>           iterator;
  +    typedef XalanMapIterator<
  +                XalanMapConstIteratorTraits<value_type>, 
  +                typename EntryListType::iterator>     const_iterator;
   
       typedef typename MemoryManagedConstructionTraits<key_type>::Constructor  
FirstConstructor;
       typedef typename MemoryManagedConstructionTraits<data_type>::Constructor 
SecondConstructor;
  @@ -238,20 +235,22 @@
                m_loadFactor(loadFactor),
                m_minBuckets(minBuckets),
                m_size(0),
  -             m_entries(*m_memoryManager),
  -             m_buckets(*m_memoryManager)
  +             m_entries(theMemoryManager),
  +        m_freeEntries(theMemoryManager),
  +             m_buckets(theMemoryManager)
        {
        }
   
        XalanMap(
                        const XalanMap &theRhs,
  -                     MemoryManagerType&  theManager) :
  -        m_memoryManager(&theManager),
  +                     MemoryManagerType&  theMemoryManager) :
  +        m_memoryManager(&theMemoryManager),
                m_loadFactor(theRhs.m_loadFactor),
                m_minBuckets(10),
                m_size(0),
  -             m_entries(*m_memoryManager),
  -             m_buckets(size_type(m_loadFactor * theRhs.size())+ 1, 
m_entries.end(), theManager)
  +             m_entries(theMemoryManager),
  +        m_freeEntries(theMemoryManager),
  +             m_buckets(size_type(m_loadFactor * theRhs.size())+ 1, 
BucketType(*m_memoryManager), theMemoryManager)
        {
                const_iterator entry = theRhs.begin();
                while(entry != theRhs.end())
  @@ -274,6 +273,16 @@
        ~XalanMap()
        {
           doRemoveEntries();
  +
  +        if (!m_buckets.empty())
  +        {
  +            EntryListType::iterator toRemove = m_freeEntries.begin();
  +            while(toRemove != m_freeEntries.end())
  +            {
  +                deallocate(toRemove->value);
  +                ++toRemove;
  +            }      
  +        }
        }
   
        XalanMap & operator=(const XalanMap& theRhs) 
  @@ -283,7 +292,6 @@
                return *this;
        }
   
  -
        size_type size() const
        {
                return m_size;
  @@ -301,7 +309,7 @@
   
        const_iterator begin() const
        {
  -             return m_entries.begin();
  +        return  const_cast<XalanMap*>(this)->begin();
        }
   
        iterator end()
  @@ -311,7 +319,7 @@
   
        const_iterator end() const 
        {
  -             return m_entries.end();
  +        return const_cast<XalanMap*>(this)->end();
        }
   
        iterator find(const key_type& key)
  @@ -321,16 +329,16 @@
                        const size_type     index = doHash(key);
               assert(index < m_buckets.size());
   
  -                     iterator bucketPos = m_buckets[index];
  +            BucketType & bucket = m_buckets[index];
  +            typename BucketType::iterator pos = bucket.begin();
   
  -                     while (bucketPos != m_entries.end() &&
  -                                bucketPos->bucketIndex == index)
  +                     while (pos != bucket.end())
                        {
  -                             if (m_equals(key,bucketPos->first))
  +                             if (!(*pos)->erased && m_equals(key, 
(*pos)->value->first))
                                {
  -                                     return bucketPos;
  +                                     return iterator(*pos);
                                }
  -                             ++bucketPos;
  +                             ++pos;
                        }
                }
   
  @@ -372,7 +380,6 @@
                }
        }
   
  -
        void erase(iterator pos)
        {
                if (pos != end())
  @@ -400,15 +407,16 @@
        {
           doRemoveEntries();
   
  -             m_size = 0;
  -
  -             XALAN_STD_QUALIFIER fill(
  -            m_buckets.begin(),
  -            m_buckets.end(),
  -            m_entries.end());
  +             BucketTableType::iterator bucketPos = m_buckets.begin();
  +             while (bucketPos != m_buckets.end())
  +             {
  +                     bucketPos->clear();
  +                     ++bucketPos;
  +             }
   
  -             m_entries.clear();
  -     }
  +        assert(0 == m_size);
  +        assert(m_entries.empty());
  +    }
   
        void swap(XalanMap& theRhs)
        {
  @@ -421,17 +429,18 @@
                theRhs.m_memoryManager = tempMemoryManager;
   
                m_entries.swap(theRhs.m_entries);
  +        m_freeEntries.swap(theRhs.m_freeEntries);
                m_buckets.swap(theRhs.m_buckets);
        }
   
  -     protected:
  +protected:
   
  -     iterator doCreateEntry(const key_type & key, const data_type*  data = 0)
  +    iterator doCreateEntry(const key_type & key, const data_type*  data = 0)
        {
                // if there are no buckets, create initial minimum set of 
buckets
                if (m_buckets.empty())
                {
  -                     m_buckets.insert(m_buckets.begin(), m_minBuckets, 
m_entries.end());
  +                     m_buckets.insert(m_buckets.begin(), m_minBuckets, 
BucketType(*m_memoryManager));
                }
   
                // if the load factor has been reached, rehash
  @@ -442,56 +451,51 @@
   
                size_type index = doHash(key);
   
  -             iterator & bucketStartPos = m_buckets[index];
  +        
  +        if (m_freeEntries.empty())
  +        {
  +            m_freeEntries.push_back(Entry(allocate(1)));
  +        }
  +        
  +        // insert a new entry as the first position in the bucket
  +        Entry& newEntry = m_freeEntries.back();
  +        newEntry.erased = false;
   
  -             // insert a new entry as the first position in the bucket
  -        Entry * newEntry = allocate(1);
  -        FirstConstructor::construct(const_cast<key_type*>(&newEntry->first), 
key, *m_memoryManager);
  +        
FirstConstructor::construct(const_cast<key_type*>(&newEntry.value->first), key, 
*m_memoryManager);
           if (data != 0)
           {
  -            SecondConstructor::construct(&newEntry->second, *data, 
*m_memoryManager);
  +            SecondConstructor::construct(&newEntry.value->second, *data, 
*m_memoryManager);
           }
           else
           {
  -             SecondConstructor::construct(&newEntry->second, 
*m_memoryManager);
  +             SecondConstructor::construct(&newEntry.value->second, 
*m_memoryManager);
           }
   
  -        new (&newEntry->bucketIndex) size_type(index);
  -             bucketStartPos = m_entries.insert(bucketStartPos, newEntry);
  -                     
  -             ++m_size;
  -             return bucketStartPos;
  +
  +        m_entries.splice(m_entries.end(), m_freeEntries, 
--m_freeEntries.end());
  +
  +        m_buckets[index].push_back(--m_entries.end());
  +
  +        ++m_size;
  +
  +             return iterator(--m_entries.end());
        }
   
        void doRemoveEntry(const iterator & toRemovePos)
  -     {
  -             size_type index = toRemovePos->bucketIndex;
  -             iterator nextPos = ++(iterator(toRemovePos));
  -
  -             // if the entry to remove is the first in the bucket
  -             // set the next entry as the first or,
  -             // if there are no more entries set it to the end
  -             if (m_buckets[index] == toRemovePos)
  -             {
  -                     if (nextPos != m_entries.end() &&
  -                nextPos->bucketIndex == index)
  -                     {
  -                             m_buckets[index] = nextPos;
  -                     }
  -                     else
  -                     {
  -                             m_buckets[index] = m_entries.end();
  -                     }
  -             }
  -        
  +     {   
           value_type& toRemove = *toRemovePos;
   #if defined(_MSC_VER) && _MSC_VER <= 1300
           toRemove.value_type::~value_type();
   #else
           toRemove.~value_type();
   #endif
  -        deallocate(&toRemove);
  -             m_entries.erase(toRemovePos);
  +        m_freeEntries.splice(
  +                m_freeEntries.end(), 
  +                m_entries, 
  +                toRemovePos.baseIterator);
  +
  +        toRemovePos.baseIterator->erased = true;
  +
                --m_size;
        }
   
  @@ -512,34 +516,16 @@
        void rehash()
        {
                // grow the number of buckets by 60%
  -             EntryPosVectorType temp(size_type(1.6 * size()), 
m_entries.end(), *m_memoryManager);
  +             BucketTableType temp(size_type(1.6 * size()), 
BucketType(*m_memoryManager), *m_memoryManager);
                m_buckets.swap(temp);
        
  -             // move current entries into a temporary list
  -             EntryListType tempEntryList(*m_memoryManager);
  -             tempEntryList.splice(tempEntryList.begin(),m_entries, 
m_entries.begin(), m_entries.end());
  -
  -             // rehash each entry assign to bucket and insert into list
  -             while (tempEntryList.begin() != tempEntryList.end())
  +        // rehash each entry assign to bucket and insert into list
  +             EntryListType::iterator entryPos = m_entries.begin();
  +             while (entryPos != m_entries.end())
                {
  -                     iterator entry = tempEntryList.begin();
  -
  -                     entry->bucketIndex = doHash(entry->first);
  -                     iterator & bucketStartPos = 
m_buckets[entry->bucketIndex];
  -
  -                     // if the bucket is empty assign to the entry and 
insert 
  -                     // into the list, otherwise insert into front of the 
  -                     // current first entry
  -                     if (bucketStartPos == m_entries.end())
  -                     {
  -                             bucketStartPos = entry;
  -                             m_entries.splice(m_entries.begin(), 
tempEntryList, entry);
  -                     }
  -                     else
  -                     {
  -                             m_entries.splice(bucketStartPos, tempEntryList, 
entry);
  -                             --bucketStartPos;
  -                     }
  +             size_type index = doHash(entryPos->value->first);
  +                     m_buckets[index].push_back(entryPos);
  +            ++entryPos;
                }
        }
   
  @@ -571,9 +557,9 @@
       }
   
        // Data members...
  -     typename KeyTraits::Hasher                                      m_hash;
  +     typename KeyTraits::Hasher                      m_hash;
                
  -     typename KeyTraits::Comparator                          m_equals;
  +     typename KeyTraits::Comparator          m_equals;
   
       MemoryManagerType*                                       m_memoryManager;
   
  @@ -583,15 +569,24 @@
   
        size_type                                                       m_size;
   
  -     EntryListType                                           m_entries;
  +    EntryListType                                            m_entries;
   
  -    EntryPosVectorType                                       m_buckets;
  +    EntryListType                       m_freeEntries;
   
  -    private:
  +    BucketTableType                                  m_buckets;
  +
  +private:
       // not defined
       XalanMap();
       XalanMap(const XalanMap&);
   };
  +
  +
  +
  +#if defined(_MSC_VER)
  +#pragma warning(pop)
  +#endif
  +
   
   
   XALAN_CPP_NAMESPACE_END
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to