/*******************************************************************************

        @file HashMap.d

        This software is provided 'as-is', without any express or implied
        warranty. In no event will the authors be held liable for damages
        of any kind arising from the use of this software.

        Permission is hereby granted to anyone to use this software for any
        purpose, including commercial applications, and to alter it and/or
        redistribute it freely, subject to the following restrictions:

        1. The origin of this software must not be misrepresented; you must
           not claim that you wrote the original software. If you use this
           software in a product, an acknowledgment within documentation of
           said product would be appreciated but is not required.

        2. Altered source versions must be plainly marked as such, and must
           not be misrepresented as being the original software.

        3. This notice may not be removed or altered from any distribution
           of the source.

        4. Derivative works are permitted, but they must carry this notice
           in full and credit the original source.


                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


        Written by Doug Lea with assistance from members of JCP JSR-166
        Expert Group and released to the public domain, as explained at
        http://creativecommons.org/licenses/publicdomain

        @version        Initial version, July 2004
        @author         Doug Lea; ported/modified by Kris

*******************************************************************************/

module mango.cache.HashMap;

/******************************************************************************

******************************************************************************/

extern (C)
{
        int memcmp (char *, char *, uint);
}


/**
 * A hash table supporting full concurrency of retrievals and
 * adjustable expected concurrency for updates. This class obeys the
 * same functional specification as {@link java.util.Hashtable}, and
 * includes versions of methods corresponding to each method of
 * <tt>Hashtable</tt>. However, even though all operations are
 * thread-safe, retrieval operations do <em>not</em> entail locking,
 * and there is <em>not</em> any support for locking the entire table
 * in a way that prevents all access.  This class is fully
 * interoperable with <tt>Hashtable</tt> in programs that rely on its
 * thread safety but not on its synchronization details.
 *
 * <p> Retrieval operations (including <tt>get</tt>) generally do not
 * block, so may overlap with update operations (including
 * <tt>put</tt> and <tt>remove</tt>). Retrievals reflect the results
 * of the most recently <em>completed</em> update operations holding
 * upon their onset.  For aggregate operations such as <tt>putAll</tt>
 * and <tt>clear</tt>, concurrent retrievals may reflect insertion or
 * removal of only some entries.  Similarly, Iterators and
 * Enumerations return elements reflecting the state of the hash table
 * at some point at or since the creation of the iterator/enumeration.
 * They do <em>not</em> throw
 * {@link ConcurrentModificationException}.  However, iterators are
 * designed to be used by only one thread at a time.
 *
 * <p> The allowed concurrency among update operations is guided by
 * the optional <tt>concurrencyLevel</tt> constructor argument
 * (default 16), which is used as a hint for internal sizing.  The
 * table is internally partitioned to try to permit the indicated
 * number of concurrent updates without contention. Because placement
 * in hash tables is essentially random, the actual concurrency will
 * vary.  Ideally, you should choose a value to accommodate as many
 * threads as will ever concurrently modify the table. Using a
 * significantly higher value than you need can waste space and time,
 * and a significantly lower value can lead to thread contention. But
 * overestimates and underestimates within an order of magnitude do
 * not usually have much noticeable impact. A value of one is
 * appropriate when it is known that only one thread will modify and
 * all others will only read. Also, resizing this or any other kind of
 * hash table is a relatively slow operation, so, when possible, it is
 * a good idea to provide estimates of expected table sizes in
 * constructors.
 *
 * <p>This class and its views and iterators implement all of the
 * <em>optional</em> methods of the {@link Map} and {@link Iterator}
 * interfaces.
 *
 * <p> Like {@link java.util.Hashtable} but unlike {@link
 * java.util.HashMap}, this class does NOT allow <tt>null</tt> to be
 * used as a key or value.
 *
 * <p>This class is a member of the
 * <a href="{@docRoot}/../guide/collections/index.html">
 * Java Collections Framework</a>.
 *
 * @since 1.5
 * @author Doug Lea
 * @param <K> the type of keys maintained by this map
 * @param <V> the type of mapped values
 */

class HashMap
{
    alias void[] K;
    alias Object V;
    alias jhash  hash;          // jhash, fnv, or walter

    /*
     * The basic strategy is to subdivide the table among Segments,
     * each of which itself is a concurrently readable hash table.
     */

    /* ---------------- Constants -------------- */

    /**
     * The default initial number of table slots for this table.
     * Used when not otherwise specified in constructor.
     */
    private const uint DEFAULT_INITIAL_CAPACITY = 16;

    /**
     * The maximum capacity, used if a higher value is implicitly
     * specified by either of the constructors with arguments.  MUST
     * be a power of two <= 1<<30 to ensure that entries are indexible
     * using ints.
     */
    private const uint MAXIMUM_CAPACITY = 1 << 30;

    /**
     * The default load factor for this table.  Used when not
     * otherwise specified in constructor.
     */
    private const float DEFAULT_LOAD_FACTOR = 0.75f;

    /**
     * The default number of concurrency control segments.
     **/
    private const uint DEFAULT_SEGMENTS = 16;

    /**
     * The maximum number of segments to allow; used to bound
     * constructor arguments.
     */
    private const uint MAX_SEGMENTS = 1 << 16; // slightly conservative


    /* ---------------- Fields -------------- */

    /**
     * Mask value for indexing into segments. The upper bits of a
     * key's hash code are used to choose the segment.
     **/
    private final int segmentMask;

    /**
     * Shift value for indexing within segments.
     **/
    private final int segmentShift;

    /**
     * The segments, each of which is a specialized hash table
     */
    private final Segment[] segments;


    /* ---------------- Small Utilities -------------- */

    /**
     * Returns a hash code for non-null Object x.
     * Uses the same hash code spreader as most other java.util hash tables.
     * @param x the object serving as a key
     * @return the hash code
     */
    private static final uint walter(K x)
    {
        uint h = typeid(char[]).getHash (&x);
        h += ~(h << 9);
        h ^=  (h >>> 14);
        h +=  (h << 4);
        h ^=  (h >>> 10);
        return h;
    }

    /**
     * Returns a hash code for non-null Object x.
     * uses the FNV hash function
     * @param x the object serving as a key
     * @return the hash code
     */
    private static final uint fnv(K x)
    {
        uint hash = 2_166_136_261;

        foreach (ubyte c; cast(ubyte[]) x)
                {
                hash ^= c;
                hash *= 16_777_619;
                }
        return hash;
    }



    /**
    * hash() -- hash a variable-length key into a 32-bit value
    *   k     : the key (the unaligned variable-length array of bytes)
    *   len   : the length of the key, counting by bytes
    *   level : can be any 4-byte value
    * Returns a 32-bit value.  Every bit of the key affects every bit of
    * the return value.  Every 1-bit and 2-bit delta achieves avalanche.
    * About 36+6len instructions.
    *
    * The best hash table sizes are powers of 2.  There is no need to do
    * mod a prime (mod is sooo slow!).  If you need less than 32 bits,
    * use a bitmask.  For example, if you need only 10 bits, do
    *   h = (h & hashmask(10));
    * In which case, the hash table should have hashsize(10) elements.
    *
    * If you are hashing n strings (ub1 **)k, do it like this:
    *   for (i=0, h=0; i<n; ++i) h = hash( k[i], len[i], h);
    *
    * By Bob Jenkins, 1996.  bob_jenkins@burtleburtle.net.  You may use this
    * code any way you wish, private, educational, or commercial.  It's free.
    *
    * See http://burlteburtle.net/bob/hash/evahash.html
    * Use for hash table lookup, or anything where one collision in 2^32 is
    * acceptable. Do NOT use for cryptographic purposes.
    */

    static final uint jhash (K x)
    {
        ubyte*  k;
        uint    a,
                b,
                c,
                len;

        len = x.length;
        k = cast(ubyte *) x;
        a = b = 0x9e3779b9;

        // the previous hash value
        c = 0;

        // handle most of the key
        while (len >= 12)
              {
              a += *cast(uint *)(k+0);
              b += *cast(uint *)(k+4);
              c += *cast(uint *)(k+8);

              a -= b; a -= c; a ^= (c>>13);
              b -= c; b -= a; b ^= (a<<8);
              c -= a; c -= b; c ^= (b>>13);
              a -= b; a -= c; a ^= (c>>12);
              b -= c; b -= a; b ^= (a<<16);
              c -= a; c -= b; c ^= (b>>5);
              a -= b; a -= c; a ^= (c>>3);
              b -= c; b -= a; b ^= (a<<10);
              c -= a; c -= b; c ^= (b>>15);
              k += 12; len -= 12;
              }

        // handle the last 11 bytes
        c += x.length;
        switch (len)
               {
               case 11: c+=(cast(uint)k[10]<<24);
               case 10: c+=(cast(uint)k[9]<<16);
               case 9 : c+=(cast(uint)k[8]<<8);
               case 8 : b+=(cast(uint)k[7]<<24);
               case 7 : b+=(cast(uint)k[6]<<16);
               case 6 : b+=(cast(uint)k[5]<<8);
               case 5 : b+=k[4];
               case 4 : a+=(cast(uint)k[3]<<24);
               case 3 : a+=(cast(uint)k[2]<<16);
               case 2 : a+=(cast(uint)k[1]<<8);
               case 1 : a+=k[0];
               default:
               }

        a -= b; a -= c; a ^= (c>>13);
        b -= c; b -= a; b ^= (a<<8);
        c -= a; c -= b; c ^= (b>>13);
        a -= b; a -= c; a ^= (c>>12);
        b -= c; b -= a; b ^= (a<<16);
        c -= a; c -= b; c ^= (b>>5);
        a -= b; a -= c; a ^= (c>>3);
        b -= c; b -= a; b ^= (a<<10);
        c -= a; c -= b; c ^= (b>>15);

        return c;
    }


    /**
     * Returns the segment that should be used for key with given hash
     * @param hash the hash code for the key
     * @return the segment
     */
    private final Segment segmentFor(uint hash)
    {
        return segments[(hash >>> segmentShift) & segmentMask];
    }

    /* ---------------- Inner Classes -------------- */

    /**
     * ConcurrentHashMap list entry. Note that this is never exported
     * out as a user-visible Map.Entry.
     *
     * Because the value field is volatile, not final, it is legal wrt
     * the Java Memory Model for an unsynchronized reader to see null
     * instead of initial value when read via a data race.  Although a
     * reordering leading to this is not likely to ever actually
     * occur, the Segment.readValueUnderLock method is used as a
     * backup in case a null (pre-initialized) value is ever seen in
     * an unsynchronized access method.
     */
    private static class HashEntry
    {
        final K         key;
        final uint      hash;
        final V         value;
        final HashEntry next;

        this (K key, uint hash, HashEntry next, V value)
        {
            this.key = key;
            this.hash = hash;
            this.next = next;
            this.value = value;
        }
    }

    /**
     * Segments are specialized versions of hash tables.  This
     * subclasses from ReentrantLock opportunistically, just to
     * simplify some locking and avoid separate construction.
     **/
    static class Segment
    {
        /*
         * Segments maintain a table of entry lists that are ALWAYS
         * kept in a consistent state, so can be read without locking.
         * Next fields of nodes are immutable (final).  All list
         * additions are performed at the front of each bin. This
         * makes it easy to check changes, and also fast to traverse.
         * When nodes would otherwise be changed, new nodes are
         * created to replace them. This works well for hash tables
         * since the bin lists tend to be short. (The average length
         * is less than two for the default load factor threshold.)
         *
         * Read operations can thus proceed without locking, but rely
         * on selected uses of volatiles to ensure that completed
         * write operations performed by other threads are
         * noticed. For most purposes, the "count" field, tracking the
         * number of elements, serves as that volatile variable
         * ensuring visibility.  This is convenient because this field
         * needs to be read in many read operations anyway:
         *
         *   - All (unsynchronized) read operations must first read the
         *     "count" field, and should not look at table entries if
         *     it is 0.
         *
         *   - All (synchronized) write operations should write to
         *     the "count" field after structurally changing any bin.
         *     The operations must not take any action that could even
         *     momentarily cause a concurrent read operation to see
         *     inconsistent data. This is made easier by the nature of
         *     the read operations in Map. For example, no operation
         *     can reveal that the table has grown but the threshold
         *     has not yet been updated, so there are no atomicity
         *     requirements for this with respect to reads.
         *
         * As a guide, all critical volatile reads and writes to the
         * count field are marked in code comments.
         */

        /**
         * The number of elements in this segment's region.
         **/
        int count;

        /**
         * The table is rehashed when its size exceeds this threshold.
         * (The value of this field is always (int)(capacity *
         * loadFactor).)
         */
        int threshold;

        /**
         * The per-segment table. Declared as a raw type, casted
         * to HashEntry<K,V> on each use.
         */
        HashEntry[] table;

        /**
         * The load factor for the hash table.  Even though this value
         * is same for all segments, it is replicated to avoid needing
         * links to outer object.
         * @serial
         */
        final float loadFactor;

        this (int initialCapacity, float lf)
        {
            loadFactor = lf;
            setTable (new HashEntry[initialCapacity]);
        }

        /**
         * Set table to new HashEntry array.
         * Call only while holding lock or in constructor.
         **/
        private final void setTable (HashEntry[] newTable)
        {
            threshold = cast(int) (newTable.length * loadFactor);
            volatile table = newTable;
        }

        /**
         * Return properly casted first entry of bin for given hash
         */
        private final HashEntry getFirst (uint hash)
        {
            HashEntry[] tab;

            volatile tab = table;
            return tab [hash & (tab.length - 1)];
        }

        /**
         * Return true if the two keys match
         */
        private static final bool matchKey (K a, K b)
        {
                if (a.length == b.length)
                    return cast(bool) (memcmp (cast(char*) a, cast(char*) b, a.length) == 0);
                return false;
        }

        /* Specialized implementations of map methods */

        final V get (K key, uint hash)
        {
            int c;

            // read-volatile
            volatile c = count;
            if (c)
               {
               HashEntry e = getFirst (hash);
               while (e)
                     {
                     if (hash == e.hash && matchKey (key, e.key))
                        {
                        V v;
                        volatile v = e.value;
                        if (v)
                            return v;

                        synchronized (this)
                                      return e.value;
                        }
                     e = e.next;
                     }
               }
            return null;
        }


        final bool containsKey (K key, uint hash)
        {
            int c;

            // read-volatile
            volatile c = count;
            if (c)
               {
               HashEntry e = getFirst (hash);
               while (e)
                     {
                     if (e.hash == hash && matchKey (key, e.key))
                         return true;
                     e = e.next;
                     }
               }
            return false;
        }



        final synchronized V replace (K key, uint hash, V newValue)
        {
                HashEntry e = getFirst(hash);
                while (e && (e.hash != hash || !matchKey (key, e.key)))
                       e = e.next;

                V oldValue = null;
                if (e)
                    volatile
                           {
                           oldValue = e.value;
                           e.value = newValue;
                           }
                return oldValue;
        }


        final synchronized V put (K key, uint hash, V value, bool onlyIfAbsent)
        {
                int c;

                volatile c = count;
                if (c++ > threshold)
                    rehash();

                HashEntry[] tab;
                volatile tab = table;
                uint index = hash & (tab.length - 1);
                HashEntry first = tab[index];
                HashEntry e = first;

                while (e && (e.hash != hash || !matchKey (key, e.key)))
                       e = e.next;

                V oldValue;
                if (e)
                   {
                   volatile oldValue = e.value;
                   if (!onlyIfAbsent)
                        volatile e.value = value;
                   }
                else
                   {
                   oldValue = null;
                   tab[index] = new HashEntry (key, hash, first, value);

                   // write-volatile
                   volatile count = c;
                   }
                return oldValue;
        }


        private final void rehash ()
        {
            HashEntry[] oldTable;

            volatile oldTable = table;
            int oldCapacity = oldTable.length;
            if (oldCapacity >= MAXIMUM_CAPACITY)
                return;

            /*
             * Reclassify nodes in each list to new Map.  Because we are
             * using power-of-two expansion, the elements from each bin
             * must either stay at same index, or move with a power of two
             * offset. We eliminate unnecessary node creation by catching
             * cases where old nodes can be reused because their next
             * fields won't change. Statistically, at the default
             * threshold, only about one-sixth of them need cloning when
             * a table doubles. The nodes they replace will be garbage
             * collectable as soon as they are no longer referenced by any
             * reader thread that may be in the midst of traversing table
             * right now.
             */

            HashEntry[] newTable = new HashEntry[oldCapacity << 1];
            threshold = cast(int) (newTable.length * loadFactor);
            int sizeMask = newTable.length - 1;

            for (int i = 0; i < oldCapacity ; ++i)
                {
                // We need to guarantee that any existing reads of old Map can
                //  proceed. So we cannot yet null out each bin.
                HashEntry e = oldTable[i];

                if (e)
                   {
                   HashEntry next = e.next;
                   uint idx = e.hash & sizeMask;

                   //  Single node on list
                   if (next is null)
                       newTable[idx] = e;
                   else
                      {
                      // Reuse trailing consecutive sequence at same slot
                      HashEntry lastRun = e;
                      int lastIdx = idx;
                      for (HashEntry last=next; last; last = last.next)
                          {
                          uint k = last.hash & sizeMask;
                          if (k != lastIdx)
                             {
                             lastIdx = k;
                             lastRun = last;
                             }
                          }
                      newTable[lastIdx] = lastRun;

                      // Clone all remaining nodes
                      for (HashEntry p = e; p !is lastRun; p = p.next)
                          {
                          uint k = p.hash & sizeMask;
                          HashEntry n = newTable[k];
                          newTable[k] = new HashEntry(p.key, p.hash, n, p.value);
                          }
                      }
                   }
                }
            volatile table = newTable;
        }

        /**
         * Remove; match on key only if value null, else match both.
         */
        final synchronized V remove (K key, uint hash, V value)
        {
                int c;
                HashEntry[] tab;

                volatile c = count - 1;
                volatile tab = table;

                uint index = hash & (tab.length - 1);
                HashEntry first = tab[index];
                HashEntry e = first;

                while (e && (e.hash != hash || !matchKey (key, e.key)))
                       e = e.next;

                V oldValue = null;
                if (e)
                   {
                   V v;
                   volatile v = e.value;
                   if (value is null || value == v)
                      {
                      oldValue = v;

                      // All entries following removed node can stay
                      // in list, but all preceding ones need to be
                      // cloned.
                      HashEntry newFirst = e.next;
                      for (HashEntry p = first; p !is e; p = p.next)
                           newFirst = new HashEntry (p.key, p.hash, newFirst, p.value);
                      tab[index] = newFirst;

                      // write-volatile
                      volatile count = c;
                      }
                   }
                return oldValue;
        }


        final synchronized void clear()
        {
            if (count)
               {
                   HashEntry[] tab;
                   volatile tab = table;

                   for (int i = 0; i < tab.length ; i++)
                        tab[i] = null;

                   // write-volatile
                   volatile count = 0;
               }
        }
    }



    /* ---------------- Public operations -------------- */

    /**
     * Creates a new, empty map with the specified initial
     * capacity and the specified load factor.
     *
     * @param initialCapacity the initial capacity. The implementation
     * performs internal sizing to accommodate this many elements.
     * @param loadFactor  the load factor threshold, used to control resizing.
     * @param concurrencyLevel the estimated number of concurrently
     * updating threads. The implementation performs internal sizing
     * to try to accommodate this many threads.
     * @throws IllegalArgumentException if the initial capacity is
     * negative or the load factor or concurrencyLevel are
     * nonpositive.
     */
    public this (uint initialCapacity, float loadFactor, uint concurrencyLevel)
    {
        assert (loadFactor > 0);

        if (concurrencyLevel > MAX_SEGMENTS)
            concurrencyLevel = MAX_SEGMENTS;

        // Find power-of-two sizes best matching arguments
        int sshift = 0;
        int ssize = 1;
        while (ssize < concurrencyLevel)
              {
              ++sshift;
              ssize <<= 1;
              }

        segmentShift = 32 - sshift;
        segmentMask = ssize - 1;
        this.segments = new Segment[ssize];

        if (initialCapacity > MAXIMUM_CAPACITY)
            initialCapacity = MAXIMUM_CAPACITY;

        int c = initialCapacity / ssize;
        if (c * ssize < initialCapacity)
            ++c;

        int cap = 1;
        while (cap < c)
               cap <<= 1;

        for (int i = 0; i < this.segments.length; ++i)
             this.segments[i] = new Segment (cap, loadFactor);
    }

    /**
     * Creates a new, empty map with the specified initial
     * capacity,  and with default load factor and concurrencyLevel.
     *
     * @param initialCapacity The implementation performs internal
     * sizing to accommodate this many elements.
     * @throws IllegalArgumentException if the initial capacity of
     * elements is negative.
     */
    public this (uint initialCapacity)
    {
        this(initialCapacity, DEFAULT_LOAD_FACTOR, DEFAULT_SEGMENTS);
    }

    /**
     * Creates a new, empty map with a default initial capacity,
     * load factor, and concurrencyLevel.
     */
    public this ()
    {
        this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR, DEFAULT_SEGMENTS);
    }

    /**
     * Returns the value to which the specified key is mapped in this table.
     *
     * @param   key   a key in the table.
     * @return  the value to which the key is mapped in this table;
     *          <tt>null</tt> if the key is not mapped to any value in
     *          this table.
     * @throws  NullPointerException  if the key is
     *               <tt>null</tt>.
     */
    public V get (K key)
    {
        uint hash = hash(key); // throws NullPointerException if key null
        return segmentFor(hash).get(key, hash);
    }

    /**
     * Tests if the specified object is a key in this table.
     *
     * @param   key   possible key.
     * @return  <tt>true</tt> if and only if the specified object
     *          is a key in this table, as determined by the
     *          <tt>equals</tt> method; <tt>false</tt> otherwise.
     * @throws  NullPointerException  if the key is
     *               <tt>null</tt>.
     */
    public bool containsKey (K key)
    {
        uint hash = hash(key); // throws NullPointerException if key null
        return segmentFor(hash).containsKey(key, hash);
    }

    /**
     * Maps the specified <tt>key</tt> to the specified
     * <tt>value</tt> in this table. Neither the key nor the
     * value can be <tt>null</tt>.
     *
     * <p> The value can be retrieved by calling the <tt>get</tt> method
     * with a key that is equal to the original key.
     *
     * @param      key     the table key.
     * @param      value   the value.
     * @return     the previous value of the specified key in this table,
     *             or <tt>null</tt> if it did not have one.
     * @throws  NullPointerException  if the key or value is
     *               <tt>null</tt>.
     */
    public V put (K key, V value)
    {
        assert (value);

        uint hash = hash(key);
        return segmentFor(hash).put(key, hash, value, false);
    }

    /**
     * If the specified key is not already associated
     * with a value, associate it with the given value.
     * This is equivalent to
     * <pre>
     *   if (!map.containsKey(key))
     *      return map.put(key, value);
     *   else
     *      return map.get(key);
     * </pre>
     * Except that the action is performed atomically.
     * @param key key with which the specified value is to be associated.
     * @param value value to be associated with the specified key.
     * @return previous value associated with specified key, or <tt>null</tt>
     *         if there was no mapping for key.
     * @throws NullPointerException if the specified key or value is
     *            <tt>null</tt>.
     */
    public V putIfAbsent (K key, V value)
    {
        assert (value);

        uint hash = hash(key);
        return segmentFor(hash).put(key, hash, value, true);
    }


    /**
     * Removes the key (and its corresponding value) from this
     * table. This method does nothing if the key is not in the table.
     *
     * @param   key   the key that needs to be removed.
     * @return  the value to which the key had been mapped in this table,
     *          or <tt>null</tt> if the key did not have a mapping.
     * @throws  NullPointerException  if the key is
     *               <tt>null</tt>.
     */
    public V remove (K key)
    {
        uint hash = hash(key);
        return segmentFor(hash).remove(key, hash, null);
    }

    /**
     * Remove entry for key only if currently mapped to given value.
     * Acts as
     * <pre>
     *  if (map.get(key).equals(value)) {
     *     map.remove(key);
     *     return true;
     * } else return false;
     * </pre>
     * except that the action is performed atomically.
     * @param key key with which the specified value is associated.
     * @param value value associated with the specified key.
     * @return true if the value was removed
     * @throws NullPointerException if the specified key is
     *            <tt>null</tt>.
     */
    public bool remove (K key, V value)
    {
        uint hash = hash(key);
        return cast(bool) (segmentFor(hash).remove(key, hash, value) !is null);
    }


    /**
     * Replace entry for key only if currently mapped to some value.
     * Acts as
     * <pre>
     *  if ((map.containsKey(key)) {
     *     return map.put(key, value);
     * } else return null;
     * </pre>
     * except that the action is performed atomically.
     * @param key key with which the specified value is associated.
     * @param value value to be associated with the specified key.
     * @return previous value associated with specified key, or <tt>null</tt>
     *         if there was no mapping for key.
     * @throws NullPointerException if the specified key or value is
     *            <tt>null</tt>.
     */
    public V replace (K key, V value)
    {
        assert (value);

        uint hash = hash(key);
        return segmentFor(hash).replace(key, hash, value);
    }


    /**
     * Removes all mappings from this map.
     */
    public void clear ()
    {
        for (int i = 0; i < segments.length; ++i)
             segments[i].clear();
    }


    /**
     * Returns an enumeration of the keys in this table.
     *
     * @return  an enumeration of the keys in this table.
     * @see     #keySet
     */
    public KeyIterator keys ()
    {
        return new KeyIterator (this);
    }

    /**
     * Returns an enumeration of the values in this table.
     *
     * @return  an enumeration of the values in this table.
     * @see     #values
     */
    public ValueIterator elements ()
    {
        return new ValueIterator (this);
    }

        /**********************************************************************

                Iterate over all keys in hashmap

        **********************************************************************/

        int opApply (int delegate(inout char[]) dg)
        {
                int result = 0;
                KeyIterator iterator = keys ();

                while (iterator.hasNext)
                      {
                      char[] ca = cast(char[]) iterator.next;
                      if ((result = dg (ca)) != 0)
                           break;
                      }
                return result;
        }

        /**********************************************************************

                Iterate over all keys in hashmap

        **********************************************************************/

        int opApply (int delegate(inout char[], inout Object) dg)
        {
                int result = 0;
                KeyIterator iterator = keys ();

                while (iterator.hasNext)
                      {
                      HashEntry he = iterator.nextElement;
                      char[] ca = cast(char[]) he.key;
                      if ((result = dg (ca, he.value)) != 0)
                           break;
                      }
                return result;
        }


    /* ---------------- Iterator Support -------------- */

    abstract static class HashIterator
    {
        int nextSegmentIndex;
        int nextTableIndex;
        HashEntry[] currentTable;
        HashEntry nextEntry;
        HashEntry lastReturned;
        HashMap   map;

        this (HashMap map)
        {
            this.map = map;
            nextSegmentIndex = map.segments.length - 1;
            nextTableIndex = -1;
            advance();
        }

        final void advance ()
        {
            if (nextEntry !is null && (nextEntry = nextEntry.next) !is null)
                return;

            while (nextTableIndex >= 0)
                  {
                  if ( (nextEntry = currentTable[nextTableIndex--]) !is null)
                        return;
                  }

            while (nextSegmentIndex >= 0)
                  {
                  Segment seg = map.segments[nextSegmentIndex--];
                  volatile if (seg.count)
                     {
                     currentTable = seg.table;
                     for (int j = currentTable.length - 1; j >= 0; --j)
                         {
                         if ((nextEntry = currentTable[j]) !is null)
                            {
                            nextTableIndex = j - 1;
                            return;
                            }
                         }
                     }
                  }
        }

        public bool hasNext ()
        {
            return cast(bool) (nextEntry !is null);
        }

        HashEntry nextElement ()
        {
            if (nextEntry is null)
                throw new Exception ("no such element in HashMap");

            lastReturned = nextEntry;
            advance ();
            return lastReturned;
        }
    }

    static class KeyIterator : HashIterator
    {
        this (HashMap map) {super (map);}
        public K next() { return super.nextElement().key; }
    }

    static class ValueIterator : HashIterator
    {
        this (HashMap map) {super (map);}
        public V next() { volatile return super.nextElement().value; }
    }

}
