/*
 * Copyright (C) 2009 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.inject.internal.util;

import com.google.inject.internal.Function;
import com.google.inject.internal.Nullable;
import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.util.AbstractCollection;
import java.util.AbstractMap;
import java.util.AbstractSet;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicReferenceArray;
import java.util.concurrent.locks.ReentrantLock;

/**
 * A framework for concurrent hash map implementations. The
 * CustomConcurrentHashMap class itself is not extensible and does not contain
 * any methods. Use {@link Builder} to create a custom concurrent hash map
 * instance. Client libraries implement {@link Strategy}, and this class
 * provides the surrounding concurrent data structure which implements {@link
 * ConcurrentMap}. Additionally supports implementing maps where {@link
 * Map#get} atomically computes values on demand (see {@link
 * Builder#buildComputingMap(ComputingStrategy, com.google.inject.internal.Function)}).
 *
 * <p>The resulting hash table supports full concurrency of retrievals and
 * adjustable expected concurrency for updates. Even though all operations are
 * thread-safe, retrieval operations do <i>not</i> entail locking,
 * and there is <i>not</i> any support for locking the entire table
 * in a way that prevents all access.
 *
 * <p>Retrieval operations (including {@link Map#get}) generally do not
 * block, so may overlap with update operations (including
 * {@link Map#put} and {@link Map#remove}). Retrievals reflect the results
 * of the most recently <i>completed</i> update operations holding
 * upon their onset. For aggregate operations such as {@link Map#putAll}
 * and {@link Map#clear}, concurrent retrievals may reflect insertion or
 * removal of only some entries. Similarly, iterators return elements
 * reflecting the state of the hash table at some point at or since the
 * creation of the iterator. They do <i>not</i> throw
 * {@link java.util.ConcurrentModificationException}. However, iterators can
 * only be used by one thread at a time.
 *
 * <p>The resulting {@link ConcurrentMap} and its views and iterators implement
 * all of the <i>optional</i> methods of the {@link java.util.Map} and {@link
 * java.util.Iterator} interfaces. Partially reclaimed entries are never
 * exposed through the views or iterators.
 *
 * <p>For example, the following strategy emulates the behavior of
 * {@link java.util.concurrent.ConcurrentHashMap}:
 *
 * <pre> {@code
 * class ConcurrentHashMapStrategy<K, V>
 *     implements CustomConcurrentHashMap.Strategy<K, V,
 *     InternalEntry<K, V>>, Serializable {
 *   public InternalEntry<K, V> newEntry(K key, int hash,
 *       InternalEntry<K, V> next) {
 *     return new InternalEntry<K, V>(key, hash, null, next);
 *   }
 *   public InternalEntry<K, V> copyEntry(K key,
 *       InternalEntry<K, V> original, InternalEntry<K, V> next) {
 *     return new InternalEntry<K, V>(key, original.hash, original.value, next);
 *   }
 *   public void setValue(InternalEntry<K, V> entry, V value) {
 *     entry.value = value;
 *   }
 *   public V getValue(InternalEntry<K, V> entry) { return entry.value; }
 *   public boolean equalKeys(K a, Object b) { return a.equals(b); }
 *   public boolean equalValues(V a, Object b) { return a.equals(b); }
 *   public int hashKey(Object key) { return key.hashCode(); }
 *   public K getKey(InternalEntry<K, V> entry) { return entry.key; }
 *   public InternalEntry<K, V> getNext(InternalEntry<K, V> entry) {
 *     return entry.next;
 *   }
 *   public int getHash(InternalEntry<K, V> entry) { return entry.hash; }
 *   public void setInternals(CustomConcurrentHashMap.Internals<K, V,
 *       InternalEntry<K, V>> internals) {} // ignored
 * }
 *
 * class InternalEntry<K, V> {
 *   final K key;
 *   final int hash;
 *   volatile V value;
 *   final InternalEntry<K, V> next;
 *   InternalEntry(K key, int hash, V value, InternalEntry<K, V> next) {
 *     this.key = key;
 *     this.hash = hash;
 *     this.value = value;
 *     this.next = next;
 *   }
 * }
 * }</pre>
 *
 * To create a {@link java.util.concurrent.ConcurrentMap} using the strategy
 * above:
 *
 * <pre>{@code
 *   ConcurrentMap<K, V> map = new CustomConcurrentHashMap.Builder()
 *       .build(new ConcurrentHashMapStrategy<K, V>());
 * }</pre>
 *
 * @author Bob Lee
 * @author Doug Lea
 */
final class CustomConcurrentHashMap {

  /** Prevents instantiation. */
  private CustomConcurrentHashMap() {}

  /**
   * Builds a custom concurrent hash map.
   */
  final static class Builder {

    float loadFactor = 0.75f;
    int initialCapacity = 16;
    int concurrencyLevel = 16;

    /**
     * Sets a custom load factor (defaults to 0.75).
     *
     * @throws IllegalArgumentException if loadFactor <= 0
     */
    public Builder loadFactor(float loadFactor) {
      if (loadFactor <= 0) {
        throw new IllegalArgumentException();
      }
      this.loadFactor = loadFactor;
      return this;
    }

    /**
     * Sets a custom initial capacity (defaults to 16). 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.
     *
     * @throws IllegalArgumentException if initialCapacity < 0
     */
    public Builder initialCapacity(int initialCapacity) {
      if (initialCapacity < 0) {
        throw new IllegalArgumentException();
      }
      this.initialCapacity = initialCapacity;
      return this;
    }

    /**
     * Guides the allowed concurrency among update operations. 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. Defaults to {@literal 16}.
     *
     * @throws IllegalArgumentException if concurrencyLevel < 0
     */
    public Builder concurrencyLevel(int concurrencyLevel) {
      if (concurrencyLevel <= 0) {
        throw new IllegalArgumentException();
      }
      this.concurrencyLevel = concurrencyLevel;
      return this;
    }

    /**
     * Creates a new concurrent hash map backed by the given strategy.
     *
     * @param strategy used to implement and manipulate the entries
     *
     * @param <K> the type of keys to be stored in the returned map
     * @param <V> the type of values to be stored in the returned map
     * @param <E> the type of internal entry to be stored in the returned map
     *
     * @throws NullPointerException if strategy is null
     */
    public <K, V, E> ConcurrentMap<K, V> buildMap(Strategy<K, V, E> strategy) {
      if (strategy == null) {
        throw new NullPointerException("strategy");
      }
      return new Impl<K, V, E>(strategy, this);
    }

    /**
     * Creates a {@link ConcurrentMap}, backed by the given strategy, that
     * supports atomic, on-demand computation of values. {@link Map#get}
     * returns the value corresponding to the given key, atomically computes
     * it using the computer function passed to this builder, or waits for
     * another thread to compute the value if necessary. Only one value will
     * be computed for each key at a given time.
     *
     * <p>If an entry's value has not finished computing yet, query methods
     * besides {@link java.util.Map#get} return immediately as if an entry
     * doesn't exist. In other words, an entry isn't externally visible until
     * the value's computation completes.
     *
     * <p>{@link Map#get} in the returned map implementation throws:
     * <ul>
     * <li>{@link NullPointerException} if the key is null or the
     *  computer returns null</li>
     * <li>or {@link ComputationException} wrapping an exception thrown by the
     *  computation</li>
     * </ul>
     *
     * <p><b>Note:</b> Callers of {@code get()} <i>must</i> ensure that the key
     *  argument is of type {@code K}. {@code Map.get()} takes {@code Object},
     *  so the key type is not checked at compile time. Passing an object of
     *  a type other than {@code K} can result in that object being unsafely
     *  passed to the computer function as type {@code K} not to mention the
     *  unsafe key being stored in the map.
     *
     * @param strategy used to implement and manipulate the entries
     * @param computer used to compute values for keys
     *
     * @param <K> the type of keys to be stored in the returned map
     * @param <V> the type of values to be stored in the returned map
     * @param <E> the type of internal entry to be stored in the returned map
     *
     * @throws NullPointerException if strategy or computer is null
     */
    public <K, V, E> ConcurrentMap<K, V> buildComputingMap(
        ComputingStrategy<K, V, E> strategy,
        Function<? super K, ? extends V> computer) {
      if (strategy == null) {
        throw new NullPointerException("strategy");
      }
      if (computer == null) {
        throw new NullPointerException("computer");
      }

      return new ComputingImpl<K, V, E>(strategy, this, computer);
    }
  }

  /**
   * Implements behavior specific to the client's concurrent hash map
   * implementation. Used by the framework to create new entries and perform
   * operations on them.
   *
   * <p>Method parameters are never null unless otherwise specified.
   *
   * <h3>Partially Reclaimed Entries</h3>
   *
   * <p>This class does <i>not</i> allow {@code null} to be used as a key.
   * Setting values to null is not permitted, but entries may have null keys
   * or values for various reasons. For example, the key or value may have
   * been garbage collected or reclaimed through other means.
   * CustomConcurrentHashMap treats entries with null keys and values as
   * "partially reclaimed" and ignores them for the most part. Entries may
   * enter a partially reclaimed state but they must not leave it. Partially
   * reclaimed entries will not be copied over during table expansions, for
   * example. Strategy implementations should proactively remove partially
   * reclaimed entries so that {@link Map#isEmpty} and {@link Map#size()}
   * return up-to-date results.
   *
   * @param <K> the type of keys to be stored in the returned map
   * @param <V> the type of values to be stored in the returned map
   * @param <E> internal entry type, not directly exposed to clients in map
   *  views
   */
  public interface Strategy<K, V, E> {

    /**
     * Constructs a new entry for the given key with a pointer to the given
     * next entry.
     *
     * <p>This method may return different entry implementations
     * depending upon whether next is null or not. For example, if next is
     * null (as will often be the case), this factory might use an entry
     * class that doesn't waste memory on an unnecessary field.
     *
     * @param key for this entry
     * @param hash of key returned by {@link #hashKey}
     * @param next entry (used when implementing a hash bucket as a linked
     *  list, for example), possibly null
     * @return a new entry
     */
    abstract E newEntry(K key, int hash, E next);

    /**
     * Creates a copy of the given entry pointing to the given next entry.
     * Copies the value and any other implementation-specific state from
     * {@code original} to the returned entry. For example,
     * CustomConcurrentHashMap might use this method when removing other
     * entries or expanding the internal table.
     *
     * @param key for {@code original} as well as the returned entry.
     *  Explicitly provided here to prevent reclamation of the key at an
     *  inopportune time in implementations that don't otherwise keep
     *  a strong reference to the key.
     * @param original entry from which the value and other
     *  implementation-specific state should be copied
     * @param newNext the next entry the new entry should point to, possibly
     *  null
     */
    E copyEntry(K key, E original, E newNext);

    /**
     * Sets the value of an entry using volatile semantics. Values are set
     * synchronously on a per-entry basis.
     *
     * @param entry to set the value on
     * @param value to set
     */
    void setValue(E entry, V value);

    /**
     * Gets the value of an entry using volatile semantics.
     *
     * @param entry to get the value from
     */
    V getValue(E entry);

    /**
     * Returns true if the two given keys are equal, false otherwise. Neither
     * key will be null.
     *
     * @param a key from inside the map
     * @param b key passed from caller, not necesarily of type K
     *
     * @see Object#equals the same contractual obligations apply here
     */
    boolean equalKeys(K a, Object b);

    /**
     * Returns true if the two given values are equal, false otherwise. Neither
     * value will be null.
     *
     * @param a value from inside the map
     * @param b value passed from caller, not necesarily of type V
     *
     * @see Object#equals the same contractual obligations apply here
     */
    boolean equalValues(V a, Object b);

    /**
     * Returns a hash code for the given key.
     *
     * @see Object#hashCode the same contractual obligations apply here
     */
    int hashKey(Object key);

    /**
     * Gets the key for the given entry. This may return null (for example,
     * if the key was reclaimed by the garbage collector).
     *
     * @param entry to get key from
     * @return key from the given entry
     */
    K getKey(E entry);

    /**
     * Gets the next entry relative to the given entry, the exact same entry
     * that was provided to {@link Strategy#newEntry} when the given entry was
     * created.
     *
     * @return the next entry or null if null was passed to
     *  {@link Strategy#newEntry}
     */
    E getNext(E entry);

    /**
     * Returns the hash code that was passed to {@link Strategy#newEntry})
     * when the given entry was created.
     */
    int getHash(E entry);

// TODO:
//    /**
//     * Notifies the strategy that an entry has been removed from the map.
//     *
//     * @param entry that was recently removed
//     */
//    void remove(E entry);

    /**
     * Provides an API for interacting directly with the map's internal
     * entries to this strategy. Invoked once when the map is created.
     * Strategies that don't need access to the map's internal entries
     * can simply ignore the argument.
     *
     * @param internals of the map, enables direct interaction with the
     *  internal entries
     */
    void setInternals(Internals<K, V, E> internals);
  }

  /**
   * Provides access to a map's internal entries.
   */
  public interface Internals<K, V, E> {

// TODO:
//    /**
//     * Returns a set view of the internal entries.
//     */
//    Set<E> entrySet();

    /**
     * Returns the internal entry corresponding to the given key from the map.
     *
     * @param key to retrieve entry for
     *
     * @throws NullPointerException if key is null
     */
    E getEntry(K key);

    /**
     * Removes the given entry from the map if the value of the entry in the
     * map matches the given value.
     *
     * @param entry to remove
     * @param value entry must have for the removal to succeed
     *
     * @throws NullPointerException if entry is null
     */
    boolean removeEntry(E entry, @Nullable V value);

    /**
     * Removes the given entry from the map.
     *
     * @param entry to remove
     *
     * @throws NullPointerException if entry is null
     */
    boolean removeEntry(E entry);
  }

  /**
   * Extends {@link Strategy} to add support for computing values on-demand.
   * Implementations should typically intialize the entry's value to a
   * placeholder value in {@link #newEntry(Object, int, Object)} so that
   * {@link #waitForValue(Object)} can tell the difference between a
   * pre-intialized value and an in-progress computation. {@link
   * #copyEntry(Object, Object, Object)} must detect and handle the case where
   * an entry is copied in the middle of a computation. Implementations can
   * throw {@link UnsupportedOperationException} in {@link #setValue(Object,
   * Object)} if they wish to prevent users from setting values directly.
   *
   * @see Builder#buildComputingMap(ComputingStrategy, Function)
   */
  public interface ComputingStrategy<K, V, E> extends Strategy<K, V, E> {

    /**
     * Computes a value for the given key and stores it in the given entry.
     * Called as a result of {@link Map#get}. If this method throws an
     * exception, CustomConcurrentHashMap will remove the entry and retry
     * the computation on subsequent requests.
     *
     * @param entry that was created
     * @param computer passed to {@link Builder#buildMap}
     *
     * @throws ComputationException if the computation threw an exception
     * @throws NullPointerException if the computer returned null
     *
     * @return the computed value
     */
    V compute(K key, E entry, Function<? super K, ? extends V> computer);

    /**
     * Gets a value from an entry waiting for the value to be set by {@link
     * #compute} if necessary. Returns null if a value isn't available at
     * which point CustomConcurrentHashMap tries to compute a new value.
     *
     * @param entry to return value from
     * @return stored value or null if the value isn't available
     *
     * @throws InterruptedException if the thread was interrupted while
     *  waiting
     */
    V waitForValue(E entry) throws InterruptedException;
  }

  /**
   * Applies a supplemental hash function to a given hash code, which defends
   * against poor quality hash functions. This is critical when the
   * concurrent hash map uses power-of-two length hash tables, that otherwise
   * encounter collisions for hash codes that do not differ in lower or upper
   * bits.
   *
   * @param h hash code
   */
  private static int rehash(int h) {
    // Spread bits to regularize both segment and index locations,
    // using variant of single-word Wang/Jenkins hash.
    h += (h << 15) ^ 0xffffcd7d;
    h ^= (h >>> 10);
    h += (h << 3);
    h ^= (h >>> 6);
    h += (h << 2) + (h << 14);
    return h ^ (h >>> 16);
  }

  /** The concurrent hash map implementation. */
  static class Impl<K, V, E> extends AbstractMap<K, V>
      implements ConcurrentMap<K, V>, Serializable {

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

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

    /**
     * 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 indexable using ints.
     */
    static final int MAXIMUM_CAPACITY = 1 << 30;

    /**
     * The maximum number of segments to allow; used to bound constructor
     * arguments.
     */
    static final int MAX_SEGMENTS = 1 << 16; // slightly conservative

    /**
     * Number of unsynchronized retries in size and containsValue methods before
     * resorting to locking. This is used to avoid unbounded retries if tables
     * undergo continuous modification which would make it impossible to obtain
     * an accurate result.
     */
    static final int RETRIES_BEFORE_LOCK = 2;

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

    /**
     * The strategy used to implement this map.
     */
    final Strategy<K, V, E> strategy;

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

    /**
     * Shift value for indexing within segments. Helps prevent entries that
     * end up in the same segment from also ending up in the same bucket.
     */
    final int segmentShift;

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

    /**
     * The load factor for the hash table.
     */
    final float loadFactor;

    /**
     * Creates a new, empty map with the specified strategy, initial capacity,
     * load factor and concurrency level.
     */
    Impl(Strategy<K, V, E> strategy, Builder builder) {
      this.loadFactor = builder.loadFactor;
      int concurrencyLevel = builder.concurrencyLevel;
      int initialCapacity = builder.initialCapacity;

      if (concurrencyLevel > MAX_SEGMENTS) {
        concurrencyLevel = MAX_SEGMENTS;
      }

      // Find power-of-two sizes best matching arguments
      int segmentShift = 0;
      int segmentCount = 1;
      while (segmentCount < concurrencyLevel) {
        ++segmentShift;
        segmentCount <<= 1;
      }
      this.segmentShift = 32 - segmentShift;
      segmentMask = segmentCount - 1;
      this.segments = newSegmentArray(segmentCount);

      if (initialCapacity > MAXIMUM_CAPACITY) {
        initialCapacity = MAXIMUM_CAPACITY;
      }

      int segmentCapacity = initialCapacity / segmentCount;
      if (segmentCapacity * segmentCount < initialCapacity) {
        ++segmentCapacity;
      }

      int segmentSize = 1;
      while (segmentSize < segmentCapacity) {
          segmentSize <<= 1;
      }
      for (int i = 0; i < this.segments.length; ++i) {
        this.segments[i] = new Segment(segmentSize);
      }

      this.strategy = strategy;

      strategy.setInternals(new InternalsImpl());
    }

    int hash(Object key) {
      int h = strategy.hashKey(key);
      return rehash(h);
    }

    class InternalsImpl implements Internals<K, V, E>, Serializable {

      static final long serialVersionUID = 0;

      public E getEntry(K key) {
        if (key == null) {
          throw new NullPointerException("key");
        }
        int hash = hash(key);
        return segmentFor(hash).getEntry(key, hash);
      }

      public boolean removeEntry(E entry, V value) {
        if (entry == null) {
          throw new NullPointerException("entry");
        }
        int hash = strategy.getHash(entry);
        return segmentFor(hash).removeEntry(entry, hash, value);
      }

      public boolean removeEntry(E entry) {
        if (entry == null) {
          throw new NullPointerException("entry");
        }
        int hash = strategy.getHash(entry);
        return segmentFor(hash).removeEntry(entry, hash);
      }
    }

    @SuppressWarnings("unchecked")
    Segment[] newSegmentArray(int ssize) {
      // Note: This is the only way I could figure out how to create
      // a segment array (the compile has a tough time with arrays of
      // inner classes of generic types apparently). Safe because we're
      // restricting what can go in the array and no one has an
      // unrestricted reference.
      return (Segment[]) Array.newInstance(Segment.class, ssize);
    }

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

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

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

    /**
     * Segments are specialized versions of hash tables.  This subclasses from
     * ReentrantLock opportunistically, just to simplify some locking and avoid
     * separate construction.
     */
    @SuppressWarnings("serial") // This class is never serialized.
    final class Segment extends ReentrantLock {

      /*
       * 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.
       */
      volatile int count;

      /**
       * Number of updates that alter the size of the table. This is used
       * during bulk-read methods to make sure they see a consistent snapshot:
       * If modCounts change during a traversal of segments computing size or
       * checking containsValue, then we might have an inconsistent view of
       * state so (usually) must retry.
       */
      int modCount;

      /**
       * The table is expanded when its size exceeds this threshold. (The
       * value of this field is always {@code (int)(capacity * loadFactor)}.)
       */
      int threshold;

      /**
       * The per-segment table.
       */
      volatile AtomicReferenceArray<E> table;

      Segment(int initialCapacity) {
        setTable(newEntryArray(initialCapacity));
      }

      AtomicReferenceArray<E> newEntryArray(int size) {
        return new AtomicReferenceArray<E>(size);
      }

      /**
       * Sets table to new HashEntry array. Call only while holding lock or in
       * constructor.
       */
      void setTable(AtomicReferenceArray<E> newTable) {
        this.threshold = (int) (newTable.length() * loadFactor);
        this.table = newTable;
      }

      /**
       * Returns properly casted first entry of bin for given hash.
       */
      E getFirst(int hash) {
        AtomicReferenceArray<E> table = this.table;
        return table.get(hash & (table.length() - 1));
      }

      /* Specialized implementations of map methods */

      public E getEntry(Object key, int hash) {
        Strategy<K, V, E> s = Impl.this.strategy;
        if (count != 0) { // read-volatile
          for (E e = getFirst(hash); e != null; e = s.getNext(e)) {
            if (s.getHash(e) != hash) {
              continue;
            }

            K entryKey = s.getKey(e);
            if (entryKey == null) {
              continue;
            }

            if (s.equalKeys(entryKey, key)) {
              return e;
            }
          }
        }

        return null;
      }

      V get(Object key, int hash) {
        E entry = getEntry(key, hash);
        if (entry == null) {
          return null;
        }

        return strategy.getValue(entry);
      }

      boolean containsKey(Object key, int hash) {
        Strategy<K, V, E> s = Impl.this.strategy;
        if (count != 0) { // read-volatile
          for (E e = getFirst(hash); e != null; e = s.getNext(e)) {
            if (s.getHash(e) != hash) {
              continue;
            }

            K entryKey = s.getKey(e);
            if (entryKey == null) {
              continue;
            }

            if (s.equalKeys(entryKey, key)) {
              // Return true only if this entry has a value.
              return s.getValue(e) != null;
            }
          }
        }

        return false;
      }

      boolean containsValue(Object value) {
        Strategy<K, V, E> s = Impl.this.strategy;
        if (count != 0) { // read-volatile
          AtomicReferenceArray<E> table = this.table;
          int length = table.length();
          for (int i = 0; i < length; i++) {
            for (E e = table.get(i); e != null; e = s.getNext(e)) {
              V entryValue = s.getValue(e);

              // If the value disappeared, this entry is partially collected,
              // and we should skip it.
              if (entryValue == null) {
                continue;
              }

              if (s.equalValues(entryValue, value)) {
                return true;
              }
            }
          }
        }

        return false;
      }

      boolean replace(K key, int hash, V oldValue, V newValue) {
        Strategy<K, V, E> s = Impl.this.strategy;
        lock();
        try {
          for (E e = getFirst(hash); e != null; e = s.getNext(e)) {
            K entryKey = s.getKey(e);
            if (s.getHash(e) == hash && entryKey != null
                && s.equalKeys(key, entryKey)) {
              // If the value disappeared, this entry is partially collected,
              // and we should pretend like it doesn't exist.
              V entryValue = s.getValue(e);
              if (entryValue == null) {
                return false;
              }

              if (s.equalValues(entryValue, oldValue)) {
                s.setValue(e, newValue);
                return true;
              }
            }
          }

          return false;
        } finally {
          unlock();
        }
      }

      V replace(K key, int hash, V newValue) {
        Strategy<K, V, E> s = Impl.this.strategy;
        lock();
        try {
          for (E e = getFirst(hash); e != null; e = s.getNext(e)) {
            K entryKey = s.getKey(e);
            if (s.getHash(e) == hash && entryKey != null
                && s.equalKeys(key, entryKey)) {
              // If the value disappeared, this entry is partially collected,
              // and we should pretend like it doesn't exist.
              V entryValue = s.getValue(e);
              if (entryValue == null) {
                return null;
              }

              s.setValue(e, newValue);
              return entryValue;
            }
          }

          return null;
        } finally {
          unlock();
        }
      }

      V put(K key, int hash, V value, boolean onlyIfAbsent) {
        Strategy<K, V, E> s = Impl.this.strategy;
        lock();
        try {
          int count = this.count;
          if (count++ > this.threshold) { // ensure capacity
            expand();
          }

          AtomicReferenceArray<E> table = this.table;
          int index = hash & (table.length() - 1);

          E first = table.get(index);

          // Look for an existing entry.
          for (E e = first; e != null; e = s.getNext(e)) {
            K entryKey = s.getKey(e);
            if (s.getHash(e) == hash && entryKey != null
                && s.equalKeys(key, entryKey)) {
              // We found an existing entry.

              // If the value disappeared, this entry is partially collected,
              // and we should pretend like it doesn't exist.
              V entryValue = s.getValue(e);
              if (onlyIfAbsent && entryValue != null) {
                return entryValue;
              }

              s.setValue(e, value);
              return entryValue;
            }
          }

          // Create a new entry.
          ++modCount;
          E newEntry = s.newEntry(key, hash, first);
          s.setValue(newEntry, value);
          table.set(index, newEntry);
          this.count = count; // write-volatile
          return null;
        } finally {
          unlock();
        }
      }

      /**
       * Expands the table if possible.
       */
      void expand() {
        AtomicReferenceArray<E> 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.
         */

        Strategy<K, V, E> s = Impl.this.strategy;
        AtomicReferenceArray<E> newTable = newEntryArray(oldCapacity << 1);
        threshold = (int) (newTable.length() * loadFactor);
        int newMask = newTable.length() - 1;
        for (int oldIndex = 0; oldIndex < oldCapacity; oldIndex++) {
          // We need to guarantee that any existing reads of old Map can
          //  proceed. So we cannot yet null out each bin.
          E head = oldTable.get(oldIndex);

          if (head != null) {
            E next = s.getNext(head);
            int headIndex = s.getHash(head) & newMask;

            // Single node on list
            if (next == null) {
              newTable.set(headIndex, head);
            } else {
              // Reuse the consecutive sequence of nodes with the same target
              // index from the end of the list. tail points to the first
              // entry in the reusable list.
              E tail = head;
              int tailIndex = headIndex;
              for (E last = next; last != null; last = s.getNext(last)) {
                int newIndex = s.getHash(last) & newMask;
                if (newIndex != tailIndex) {
                  // The index changed. We'll need to copy the previous entry.
                  tailIndex = newIndex;
                  tail = last;
                }
              }
              newTable.set(tailIndex, tail);

              // Clone nodes leading up to the tail.
              for (E e = head; e != tail; e = s.getNext(e)) {
                K key = s.getKey(e);
                if (key != null) {
                  int newIndex = s.getHash(e) & newMask;
                  E newNext = newTable.get(newIndex);
                  newTable.set(newIndex, s.copyEntry(key, e, newNext));
                } else {
                  // Key was reclaimed. Skip entry.
                }
              }
            }
          }
        }
        table = newTable;
      }

      V remove(Object key, int hash) {
        Strategy<K, V, E> s = Impl.this.strategy;
        lock();
        try {
          int count = this.count - 1;
          AtomicReferenceArray<E> table = this.table;
          int index = hash & (table.length() - 1);
          E first = table.get(index);

          for (E e = first; e != null; e = s.getNext(e)) {
            K entryKey = s.getKey(e);
            if (s.getHash(e) == hash && entryKey != null
                && s.equalKeys(entryKey, key)) {
              V entryValue = strategy.getValue(e);
              // All entries following removed node can stay
              // in list, but all preceding ones need to be
              // cloned.
              ++modCount;
              E newFirst = s.getNext(e);
              for (E p = first; p != e; p = s.getNext(p)) {
                K pKey = s.getKey(p);
                if (pKey != null) {
                  newFirst = s.copyEntry(pKey, p, newFirst);
                } else {
                  // Key was reclaimed. Skip entry.
                }
              }
              table.set(index, newFirst);
              this.count = count; // write-volatile
              return entryValue;
            }
          }

          return null;
        } finally {
          unlock();
        }
      }

      boolean remove(Object key, int hash, Object value) {
        Strategy<K, V, E> s = Impl.this.strategy;
        lock();
        try {
          int count = this.count - 1;
          AtomicReferenceArray<E> table = this.table;
          int index = hash & (table.length() - 1);
          E first = table.get(index);

          for (E e = first; e != null; e = s.getNext(e)) {
            K entryKey = s.getKey(e);
            if (s.getHash(e) == hash && entryKey != null
                && s.equalKeys(entryKey, key)) {
              V entryValue = strategy.getValue(e);
              if (value == entryValue || (value != null && entryValue != null
                  && s.equalValues(entryValue, value))) {
                // All entries following removed node can stay
                // in list, but all preceding ones need to be
                // cloned.
                ++modCount;
                E newFirst = s.getNext(e);
                for (E p = first; p != e; p = s.getNext(p)) {
                  K pKey = s.getKey(p);
                  if (pKey != null) {
                    newFirst = s.copyEntry(pKey, p, newFirst);
                  } else {
                    // Key was reclaimed. Skip entry.
                  }
                }
                table.set(index, newFirst);
                this.count = count; // write-volatile
                return true;
              } else {
                return false;
              }
            }
          }

          return false;
        } finally {
          unlock();
        }
      }

      public boolean removeEntry(E entry, int hash, V value) {
        Strategy<K, V, E> s = Impl.this.strategy;
        lock();
        try {
          int count = this.count - 1;
          AtomicReferenceArray<E> table = this.table;
          int index = hash & (table.length() - 1);
          E first = table.get(index);

          for (E e = first; e != null; e = s.getNext(e)) {
            if (s.getHash(e) == hash && entry.equals(e)) {
              V entryValue = s.getValue(e);
              if (entryValue == value || (value != null
                  && s.equalValues(entryValue, value))) {
                // All entries following removed node can stay
                // in list, but all preceding ones need to be
                // cloned.
                ++modCount;
                E newFirst = s.getNext(e);
                for (E p = first; p != e; p = s.getNext(p)) {
                  K pKey = s.getKey(p);
                  if (pKey != null) {
                    newFirst = s.copyEntry(pKey, p, newFirst);
                  } else {
                    // Key was reclaimed. Skip entry.
                  }
                }
                table.set(index, newFirst);
                this.count = count; // write-volatile
                return true;
              } else {
                return false;
              }
            }
          }

          return false;
        } finally {
          unlock();
        }
      }

      public boolean removeEntry(E entry, int hash) {
        Strategy<K, V, E> s = Impl.this.strategy;
        lock();
        try {
          int count = this.count - 1;
          AtomicReferenceArray<E> table = this.table;
          int index = hash & (table.length() - 1);
          E first = table.get(index);

          for (E e = first; e != null; e = s.getNext(e)) {
            if (s.getHash(e) == hash && entry.equals(e)) {
              // All entries following removed node can stay
              // in list, but all preceding ones need to be
              // cloned.
              ++modCount;
              E newFirst = s.getNext(e);
              for (E p = first; p != e; p = s.getNext(p)) {
                K pKey = s.getKey(p);
                if (pKey != null) {
                  newFirst = s.copyEntry(pKey, p, newFirst);
                } else {
                  // Key was reclaimed. Skip entry.
                }
              }
              table.set(index, newFirst);
              this.count = count; // write-volatile
              return true;
            }
          }

          return false;
        } finally {
          unlock();
        }
      }

      void clear() {
        if (count != 0) {
          lock();
          try {
            AtomicReferenceArray<E> table = this.table;
            for (int i = 0; i < table.length(); i++) {
              table.set(i, null);
            }
            ++modCount;
            count = 0; // write-volatile
          } finally {
            unlock();
          }
        }
      }
    }

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

    /**
     * Returns {@code true} if this map contains no key-value mappings.
     *
     * @return {@code true} if this map contains no key-value mappings
     */
    @Override public boolean isEmpty() {
      final Segment[] segments = this.segments;
      /*
       * We keep track of per-segment modCounts to avoid ABA
       * problems in which an element in one segment was added and
       * in another removed during traversal, in which case the
       * table was never actually empty at any point. Note the
       * similar use of modCounts in the size() and containsValue()
       * methods, which are the only other methods also susceptible
       * to ABA problems.
       */
      int[] mc = new int[segments.length];
      int mcsum = 0;
      for (int i = 0; i < segments.length; ++i) {
        if (segments[i].count != 0) {
          return false;
        } else {
          mcsum += mc[i] = segments[i].modCount;
        }
      }
      // If mcsum happens to be zero, then we know we got a snapshot
      // before any modifications at all were made.  This is
      // probably common enough to bother tracking.
      if (mcsum != 0) {
        for (int i = 0; i < segments.length; ++i) {
          if (segments[i].count != 0 ||
              mc[i] != segments[i].modCount) {
            return false;
          }
        }
      }
      return true;
    }

    /**
     * Returns the number of key-value mappings in this map.  If the map
     * contains more than {@code Integer.MAX_VALUE} elements, returns
     * {@code Integer.MAX_VALUE}.
     *
     * @return the number of key-value mappings in this map
     */
    @Override public int size() {
      final Segment[] segments = this.segments;
      long sum = 0;
      long check = 0;
      int[] mc = new int[segments.length];
      // Try a few times to get accurate count. On failure due to
      // continuous async changes in table, resort to locking.
      for (int k = 0; k < RETRIES_BEFORE_LOCK; ++k) {
        check = 0;
        sum = 0;
        int mcsum = 0;
        for (int i = 0; i < segments.length; ++i) {
          sum += segments[i].count;
          mcsum += mc[i] = segments[i].modCount;
        }
        if (mcsum != 0) {
          for (int i = 0; i < segments.length; ++i) {
            check += segments[i].count;
            if (mc[i] != segments[i].modCount) {
              check = -1; // force retry
              break;
            }
          }
        }
        if (check == sum) {
          break;
        }
      }
      if (check != sum) { // Resort to locking all segments
        sum = 0;
        for (Segment segment : segments) {
          segment.lock();
        }
        for (Segment segment : segments) {
          sum += segment.count;
        }
        for (Segment segment : segments) {
          segment.unlock();
        }
      }
      if (sum > Integer.MAX_VALUE) {
        return Integer.MAX_VALUE;
      } else {
        return (int) sum;
      }
    }

    /**
     * Returns the value to which the specified key is mapped, or {@code null}
     * if this map contains no mapping for the key.
     *
     * <p>More formally, if this map contains a mapping from a key {@code k} to
     * a value {@code v} such that {@code key.equals(k)}, then this method
     * returns {@code v}; otherwise it returns {@code null}.  (There can be at
     * most one such mapping.)
     *
     * @throws NullPointerException if the specified key is null
     */
    @Override public V get(Object key) {
      if (key == null) {
        throw new NullPointerException("key");
      }
      int hash = hash(key);
      return segmentFor(hash).get(key, hash);
    }

    /**
     * Tests if the specified object is a key in this table.
     *
     * @param key possible key
     * @return {@code true} if and only if the specified object is a key in
     *         this table, as determined by the {@code equals} method;
     *         {@code false} otherwise.
     * @throws NullPointerException if the specified key is null
     */
    @Override public boolean containsKey(Object key) {
      if (key == null) {
        throw new NullPointerException("key");
      }
      int hash = hash(key);
      return segmentFor(hash).containsKey(key, hash);
    }

    /**
     * Returns {@code true} if this map maps one or more keys to the specified
     * value. Note: This method requires a full internal traversal of the hash
     * table, and so is much slower than method {@code containsKey}.
     *
     * @param value value whose presence in this map is to be tested
     * @return {@code true} if this map maps one or more keys to the specified
     *         value
     * @throws NullPointerException if the specified value is null
     */
    @Override public boolean containsValue(Object value) {
      if (value == null) {
        throw new NullPointerException("value");
      }

      // See explanation of modCount use above

      final Segment[] segments = this.segments;
      int[] mc = new int[segments.length];

      // Try a few times without locking
      for (int k = 0; k < RETRIES_BEFORE_LOCK; ++k) {
        int mcsum = 0;
        for (int i = 0; i < segments.length; ++i) {
          @SuppressWarnings("UnusedDeclaration")
          int c = segments[i].count;
          mcsum += mc[i] = segments[i].modCount;
          if (segments[i].containsValue(value)) {
            return true;
          }
        }
        boolean cleanSweep = true;
        if (mcsum != 0) {
          for (int i = 0; i < segments.length; ++i) {
            @SuppressWarnings("UnusedDeclaration")
            int c = segments[i].count;
            if (mc[i] != segments[i].modCount) {
              cleanSweep = false;
              break;
            }
          }
        }
        if (cleanSweep) {
          return false;
        }
      }
      // Resort to locking all segments
      for (Segment segment : segments) {
        segment.lock();
      }
      boolean found = false;
      try {
        for (Segment segment : segments) {
          if (segment.containsValue(value)) {
            found = true;
            break;
          }
        }
      } finally {
        for (Segment segment : segments) {
          segment.unlock();
        }
      }
      return found;
    }

    /**
     * Maps the specified key to the specified value in this table. Neither the
     * key nor the value can be null.
     *
     * <p> The value can be retrieved by calling the {@code get} method with a
     * key that is equal to the original key.
     *
     * @param key   key with which the specified value is to be associated
     * @param value value to be associated with the specified key
     * @return the previous value associated with {@code key}, or {@code null}
     *         if there was no mapping for {@code key}
     * @throws NullPointerException if the specified key or value is null
     */
    @Override public V put(K key, V value) {
      if (key == null) {
        throw new NullPointerException("key");
      }
      if (value == null) {
        throw new NullPointerException("value");
      }
      int hash = hash(key);
      return segmentFor(hash).put(key, hash, value, false);
    }

    /**
     * {@inheritDoc}
     *
     * @return the previous value associated with the specified key, or
     *         {@code null} if there was no mapping for the key
     * @throws NullPointerException if the specified key or value is null
     */
    public V putIfAbsent(K key, V value) {
      if (key == null) {
        throw new NullPointerException("key");
      }
      if (value == null) {
        throw new NullPointerException("value");
      }
      int hash = hash(key);
      return segmentFor(hash).put(key, hash, value, true);
    }

    /**
     * Copies all of the mappings from the specified map to this one. These
     * mappings replace any mappings that this map had for any of the keys
     * currently in the specified map.
     *
     * @param m mappings to be stored in this map
     */
    @Override public void putAll(Map<? extends K, ? extends V> m) {
      for (Entry<? extends K, ? extends V> e : m.entrySet()) {
        put(e.getKey(), e.getValue());
      }
    }

    /**
     * Removes the key (and its corresponding value) from this map. This method
     * does nothing if the key is not in the map.
     *
     * @param key the key that needs to be removed
     * @return the previous value associated with {@code key}, or {@code null}
     *         if there was no mapping for {@code key}
     * @throws NullPointerException if the specified key is null
     */
    @Override public V remove(Object key) {
      if (key == null) {
        throw new NullPointerException("key");
      }
      int hash = hash(key);
      return segmentFor(hash).remove(key, hash);
    }

    /**
     * {@inheritDoc}
     *
     * @throws NullPointerException if the specified key is null
     */
    public boolean remove(Object key, Object value) {
      if (key == null) {
        throw new NullPointerException("key");
      }
      int hash = hash(key);
      return segmentFor(hash).remove(key, hash, value);
    }

    /**
     * {@inheritDoc}
     *
     * @throws NullPointerException if any of the arguments are null
     */
    public boolean replace(K key, V oldValue, V newValue) {
      if (key == null) {
        throw new NullPointerException("key");
      }
      if (oldValue == null) {
        throw new NullPointerException("oldValue");
      }
      if (newValue == null) {
        throw new NullPointerException("newValue");
      }
      int hash = hash(key);
      return segmentFor(hash).replace(key, hash, oldValue, newValue);
    }

    /**
     * {@inheritDoc}
     *
     * @return the previous value associated with the specified key, or
     *         {@code null} if there was no mapping for the key
     * @throws NullPointerException if the specified key or value is null
     */
    public V replace(K key, V value) {
      if (key == null) {
        throw new NullPointerException("key");
      }
      if (value == null) {
        throw new NullPointerException("value");
      }
      int hash = hash(key);
      return segmentFor(hash).replace(key, hash, value);
    }

    /**
     * Removes all of the mappings from this map.
     */
    @Override public void clear() {
      for (Segment segment : segments) {
        segment.clear();
      }
    }

    Set<K> keySet;

    /**
     * Returns a {@link java.util.Set} view of the keys contained in this map.
     * The set is backed by the map, so changes to the map are reflected in the
     * set, and vice-versa. The set supports element removal, which removes the
     * corresponding mapping from this map, via the {@code Iterator.remove},
     * {@code Set.remove}, {@code removeAll}, {@code retainAll}, and
     * {@code clear} operations. It does not support the {@code add} or
     * {@code addAll} operations.
     *
     * <p>The view's {@code iterator} is a "weakly consistent" iterator that
     * will never throw {@link java.util.ConcurrentModificationException}, and
     * guarantees to traverse elements as they existed upon construction of the
     * iterator, and may (but is not guaranteed to) reflect any modifications
     * subsequent to construction.
     */
    @Override public Set<K> keySet() {
      Set<K> ks = keySet;
      return (ks != null) ? ks : (keySet = new KeySet());
    }

    Collection<V> values;

    /**
     * Returns a {@link java.util.Collection} view of the values contained in
     * this map. The collection is backed by the map, so changes to the map are
     * reflected in the collection, and vice-versa. The collection supports
     * element removal, which removes the corresponding mapping from this map,
     * via the {@code Iterator.remove}, {@code Collection.remove},
     * {@code removeAll}, {@code retainAll}, and {@code clear} operations. It
     * does not support the {@code add} or {@code addAll} operations.
     *
     * <p>The view's {@code iterator} is a "weakly consistent" iterator that
     * will never throw {@link java.util.ConcurrentModificationException}, and
     * guarantees to traverse elements as they existed upon construction of the
     * iterator, and may (but is not guaranteed to) reflect any modifications
     * subsequent to construction.
     */
    @Override public Collection<V> values() {
      Collection<V> vs = values;
      return (vs != null) ? vs : (values = new Values());
    }

    Set<Entry<K, V>> entrySet;

    /**
     * Returns a {@link java.util.Set} view of the mappings contained in this
     * map. The set is backed by the map, so changes to the map are reflected in
     * the set, and vice-versa. The set supports element removal, which removes
     * the corresponding mapping from the map, via the {@code Iterator.remove},
     * {@code Set.remove}, {@code removeAll}, {@code retainAll}, and
     * {@code clear} operations. It does not support the {@code add} or
     * {@code addAll} operations.
     *
     * <p>The view's {@code iterator} is a "weakly consistent" iterator that
     * will never throw {@link java.util.ConcurrentModificationException}, and
     * guarantees to traverse elements as they existed upon construction of the
     * iterator, and may (but is not guaranteed to) reflect any modifications
     * subsequent to construction.
     */
    public Set<Entry<K, V>> entrySet() {
      Set<Entry<K, V>> es = entrySet;
      return (es != null) ? es : (entrySet = new EntrySet());
    }

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

    abstract class HashIterator {

      int nextSegmentIndex;
      int nextTableIndex;
      AtomicReferenceArray<E> currentTable;
      E nextEntry;
      WriteThroughEntry nextExternal;
      WriteThroughEntry lastReturned;

      HashIterator() {
        nextSegmentIndex = segments.length - 1;
        nextTableIndex = -1;
        advance();
      }

      public boolean hasMoreElements() {
        return hasNext();
      }

      final void advance() {
        nextExternal = null;

        if (nextInChain()) {
          return;
        }

        if (nextInTable()) {
          return;
        }

        while (nextSegmentIndex >= 0) {
          Segment seg = segments[nextSegmentIndex--];
          if (seg.count != 0) {
            currentTable = seg.table;
            nextTableIndex = currentTable.length() - 1;
            if (nextInTable()) {
              return;
            }
          }
        }
      }

      /**
       * Finds the next entry in the current chain. Returns true if an entry
       * was found.
       */
      boolean nextInChain() {
        Strategy<K, V, E> s = Impl.this.strategy;
        if (nextEntry != null) {
          for (nextEntry = s.getNext(nextEntry); nextEntry != null;
              nextEntry = s.getNext(nextEntry)) {
            if (advanceTo(nextEntry)) {
              return true;
            }
          }
        }
        return false;
      }

      /**
       * Finds the next entry in the current table. Returns true if an entry
       * was found.
       */
      boolean nextInTable() {
        while (nextTableIndex >= 0) {
          if ((nextEntry = currentTable.get(nextTableIndex--)) != null) {
            if (advanceTo(nextEntry) || nextInChain()) {
              return true;
            }
          }
        }
        return false;
      }

      /**
       * Advances to the given entry. Returns true if the entry was valid,
       * false if it should be skipped.
       */
      boolean advanceTo(E entry) {
        Strategy<K, V, E> s = Impl.this.strategy;
        K key = s.getKey(entry);
        V value = s.getValue(entry);
        if (key != null && value != null) {
          nextExternal = new WriteThroughEntry(key, value);
          return true;
        } else {
          // Skip partially reclaimed entry.
          return false;
        }
      }

      public boolean hasNext() {
        return nextExternal != null;
      }

      WriteThroughEntry nextEntry() {
        if (nextExternal == null) {
          throw new NoSuchElementException();
        }
        lastReturned = nextExternal;
        advance();
        return lastReturned;
      }

      public void remove() {
        if (lastReturned == null) {
          throw new IllegalStateException();
        }
        Impl.this.remove(lastReturned.getKey());
        lastReturned = null;
      }
    }

    final class KeyIterator extends HashIterator implements Iterator<K> {

      public K next() {
        return super.nextEntry().getKey();
      }
    }

    final class ValueIterator extends HashIterator implements Iterator<V> {

      public V next() {
        return super.nextEntry().getValue();
      }
    }

    /**
     * Custom Entry class used by EntryIterator.next(), that relays setValue
     * changes to the underlying map.
     */
    final class WriteThroughEntry extends AbstractMapEntry<K, V> {
      final K key;
      V value;

      WriteThroughEntry(K key, V value) {
        this.key = key;
        this.value = value;
      }

      public K getKey() {
        return key;
      }

      public V getValue() {
        return value;
      }

      /**
       * Set our entry's value and write through to the map. The value to
       * return is somewhat arbitrary here. Since a WriteThroughEntry does not
       * necessarily track asynchronous changes, the most recent "previous"
       * value could be different from what we return (or could even have been
       * removed in which case the put will re-establish). We do not and
       * cannot guarantee more.
       */
      @Override public V setValue(V value) {
        if (value == null) {
          throw new NullPointerException();
        }
        V oldValue = Impl.this.put(getKey(), value);
        this.value = value;
        return oldValue;
      }
    }

    final class EntryIterator extends HashIterator
        implements Iterator<Entry<K, V>> {

      public Entry<K, V> next() {
        return nextEntry();
      }
    }

    final class KeySet extends AbstractSet<K> {

      public Iterator<K> iterator() {
        return new KeyIterator();
      }

      public int size() {
        return Impl.this.size();
      }

      @Override public boolean isEmpty() {
        return Impl.this.isEmpty();
      }

      @Override public boolean contains(Object o) {
        return Impl.this.containsKey(o);
      }

      @Override public boolean remove(Object o) {
        return Impl.this.remove(o) != null;
      }

      @Override public void clear() {
        Impl.this.clear();
      }
    }

    final class Values extends AbstractCollection<V> {

      public Iterator<V> iterator() {
        return new ValueIterator();
      }

      public int size() {
        return Impl.this.size();
      }

      @Override public boolean isEmpty() {
        return Impl.this.isEmpty();
      }

      @Override public boolean contains(Object o) {
        return Impl.this.containsValue(o);
      }

      @Override public void clear() {
        Impl.this.clear();
      }
    }

    final class EntrySet extends AbstractSet<Entry<K, V>> {

      public Iterator<Entry<K, V>> iterator() {
        return new EntryIterator();
      }

      @Override public boolean contains(Object o) {
        if (!(o instanceof Entry)) {
          return false;
        }
        Entry<?, ?> e = (Entry<?, ?>) o;
        Object key = e.getKey();
        if (key == null) {
          return false;
        }
        V v = Impl.this.get(key);

        return v != null && strategy.equalValues(v, e.getValue());
      }

      @Override public boolean remove(Object o) {
        if (!(o instanceof Entry)) {
          return false;
        }
        Entry<?, ?> e = (Entry<?, ?>) o;
        Object key = e.getKey();
        return key != null && Impl.this.remove(key, e.getValue());
      }

      public int size() {
        return Impl.this.size();
      }

      @Override public boolean isEmpty() {
        return Impl.this.isEmpty();
      }

      @Override public void clear() {
        Impl.this.clear();
      }
    }

    /* ---------------- Serialization Support -------------- */

    private static final long serialVersionUID = 0;

    private void writeObject(java.io.ObjectOutputStream out)
        throws IOException {
      out.writeInt(size());
      out.writeFloat(loadFactor);
      out.writeInt(segments.length); // concurrencyLevel
      out.writeObject(strategy);
      for (Entry<K, V> entry : entrySet()) {
        out.writeObject(entry.getKey());
        out.writeObject(entry.getValue());
      }
      out.writeObject(null); // terminate entries
    }

    /**
     * Fields used during deserialization. We use a nested class so we don't
     * load them until we need them. We need to use reflection to set final
     * fields outside of the constructor.
     */
    static class Fields {

      static final Field loadFactor = findField("loadFactor");
      static final Field segmentShift = findField("segmentShift");
      static final Field segmentMask = findField("segmentMask");
      static final Field segments = findField("segments");
      static final Field strategy = findField("strategy");

      static Field findField(String name) {
        try {
          Field f = Impl.class.getDeclaredField(name);
          f.setAccessible(true);
          return f;
        } catch (NoSuchFieldException e) {
          throw new AssertionError(e);
        }
      }
    }

    @SuppressWarnings("unchecked")
    private void readObject(java.io.ObjectInputStream in)
        throws IOException, ClassNotFoundException {
      try {
        int initialCapacity = in.readInt();
        float loadFactor = in.readFloat();
        int concurrencyLevel = in.readInt();
        Strategy<K, V, E> strategy = (Strategy<K, V, E>) in.readObject();

        Fields.loadFactor.set(this, loadFactor);

        if (concurrencyLevel > MAX_SEGMENTS) {
          concurrencyLevel = MAX_SEGMENTS;
        }

        // Find power-of-two sizes best matching arguments
        int segmentShift = 0;
        int segmentCount = 1;
        while (segmentCount < concurrencyLevel) {
          ++segmentShift;
          segmentCount <<= 1;
        }
        Fields.segmentShift.set(this, 32 - segmentShift);
        Fields.segmentMask.set(this, segmentCount - 1);
        Fields.segments.set(this, newSegmentArray(segmentCount));

        if (initialCapacity > MAXIMUM_CAPACITY) {
          initialCapacity = MAXIMUM_CAPACITY;
        }

        int segmentCapacity = initialCapacity / segmentCount;
        if (segmentCapacity * segmentCount < initialCapacity) {
          ++segmentCapacity;
        }

        int segmentSize = 1;
        while (segmentSize < segmentCapacity) {
            segmentSize <<= 1;
        }
        for (int i = 0; i < this.segments.length; ++i) {
          this.segments[i] = new Segment(segmentSize);
        }

        Fields.strategy.set(this, strategy);

        while (true) {
          K key = (K) in.readObject();
          if (key == null) {
            break; // terminator
          }
          V value = (V) in.readObject();
          put(key, value);
        }
      } catch (IllegalAccessException e) {
        throw new AssertionError(e);
      }
    }
  }

  static class ComputingImpl<K, V, E> extends Impl<K, V, E> {

    static final long serialVersionUID = 0;

    final ComputingStrategy<K, V, E> computingStrategy;
    final Function<? super K, ? extends V> computer;

    /**
     * Creates a new, empty map with the specified strategy, initial capacity,
     * load factor and concurrency level.
     */
    ComputingImpl(ComputingStrategy<K, V, E> strategy, Builder builder,
        Function<? super K, ? extends V> computer) {
      super(strategy, builder);
      this.computingStrategy = strategy;
      this.computer = computer;
    }

    @Override public V get(Object k) {
      /*
       * This cast isn't safe, but we can rely on the fact that K is almost
       * always passed to Map.get(), and tools like IDEs and Findbugs can
       * catch situations where this isn't the case.
       *
       * The alternative is to add an overloaded method, but the chances of
       * a user calling get() instead of the new API and the risks inherent
       * in adding a new API outweigh this little hole.
       */
      @SuppressWarnings("unchecked")
      K key = (K) k;

      if (key == null) {
        throw new NullPointerException("key");
      }

      int hash = hash(key);
      Segment segment = segmentFor(hash);
      outer: while (true) {
        E entry = segment.getEntry(key, hash);
        if (entry == null) {
          boolean created = false;
          segment.lock();
          try {
            // Try again--an entry could have materialized in the interim.
            entry = segment.getEntry(key, hash);
            if (entry == null) {
              // Create a new entry.
              created = true;
              int count = segment.count;
              if (count++ > segment.threshold) { // ensure capacity
                segment.expand();
              }
              AtomicReferenceArray<E> table = segment.table;
              int index = hash & (table.length() - 1);
              E first = table.get(index);
              ++segment.modCount;
              entry = computingStrategy.newEntry(key, hash, first);
              table.set(index, entry);
              segment.count = count; // write-volatile
            }
          } finally {
            segment.unlock();
          }

          if (created) {
            // This thread solely created the entry.
            boolean success = false;
            try {
              V value = computingStrategy.compute(key, entry, computer);
              if (value == null) {
                throw new NullPointerException(
                    "compute() returned null unexpectedly");
              }
              success = true;
              return value;
            } finally {
              if (!success) {
                segment.removeEntry(entry, hash);
              }
            }
          }
        }

        // The entry already exists. Wait for the computation.
        boolean interrupted = false;
        try {
          while (true) {
            try {
              V value = computingStrategy.waitForValue(entry);
              if (value == null) {
                // Purge entry and try again.
                segment.removeEntry(entry, hash);
                continue outer;
              }
              return value;
            } catch (InterruptedException e) {
              interrupted = true;
            }
          }
        } finally {
          if (interrupted) {
            Thread.currentThread().interrupt();
          }
        }
      }
    }
  }

  /**
   * A basic, no-frills implementation of {@code Strategy} using {@link
   * SimpleInternalEntry}. Intended to be subclassed to provide customized
   * behavior. For example, the following creates a map that uses byte arrays as
   * keys: <pre>   {@code
   *
   *   return new CustomConcurrentHashMap.Builder().buildMap(
   *       new SimpleStrategy<byte[], V>() {
   *         public int hashKey(Object key) {
   *           return Arrays.hashCode((byte[]) key);
   *         }
   *         public boolean equalKeys(byte[] a, Object b) {
   *           return Arrays.equals(a, (byte[]) b);
   *         }
   *       });}</pre>
   *
   * With nothing overridden, it yields map behavior equivalent to that of
   * {@link ConcurrentHashMap}.
   */
  static class SimpleStrategy<K, V>
      implements Strategy<K, V, SimpleInternalEntry<K, V>> {
    public SimpleInternalEntry<K, V> newEntry(
        K key, int hash, SimpleInternalEntry<K, V> next) {
      return new SimpleInternalEntry<K, V>(key, hash, null, next);
    }
    public SimpleInternalEntry<K, V> copyEntry(K key,
        SimpleInternalEntry<K, V> original, SimpleInternalEntry<K, V> next) {
      return new SimpleInternalEntry<K, V>(
          key, original.hash, original.value, next);
    }
    public void setValue(SimpleInternalEntry<K, V> entry, V value) {
      entry.value = value;
    }
    public V getValue(SimpleInternalEntry<K, V> entry) {
      return entry.value;
    }
    public boolean equalKeys(K a, Object b) {
      return a.equals(b);
    }
    public boolean equalValues(V a, Object b) {
      return a.equals(b);
    }
    public int hashKey(Object key) {
      return key.hashCode();
    }
    public K getKey(SimpleInternalEntry<K, V> entry) {
      return entry.key;
    }
    public SimpleInternalEntry<K, V> getNext(SimpleInternalEntry<K, V> entry) {
      return entry.next;
    }
    public int getHash(SimpleInternalEntry<K, V> entry) {
      return entry.hash;
    }
    public void setInternals(
        Internals<K, V, SimpleInternalEntry<K, V>> internals) {
      // ignore?
    }
  }

  /**
   * A basic, no-frills entry class used by {@link SimpleInternalEntry}.
   */
  static class SimpleInternalEntry<K, V> {
    final K key;
    final int hash;
    final SimpleInternalEntry<K, V> next;
    volatile V value;
    SimpleInternalEntry(
        K key, int hash, @Nullable V value, SimpleInternalEntry<K, V> next) {
      this.key = key;
      this.hash = hash;
      this.value = value;
      this.next = next;
    }
  }
}
