11d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/*
21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Copyright (C) 2010 The Guava Authors
31d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
41d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
51d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * in compliance with the License. You may obtain a copy of the License at
61d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
71d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * http://www.apache.org/licenses/LICENSE-2.0
81d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
91d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Unless required by applicable law or agreed to in writing, software distributed under the License
101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * or implied. See the License for the specific language governing permissions and limitations under
121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * the License.
131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */
141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpackage com.google.common.collect;
161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.base.Preconditions.checkNotNull;
181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.base.Preconditions.checkState;
191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.base.Equivalence;
211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.base.Function;
221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.collect.MapMaker.RemovalCause;
231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.collect.MapMaker.RemovalListener;
241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.io.IOException;
261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.io.ObjectInputStream;
271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.io.ObjectOutputStream;
281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.lang.ref.ReferenceQueue;
291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.ConcurrentMap;
301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.ExecutionException;
311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.atomic.AtomicReferenceArray;
321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport javax.annotation.Nullable;
341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport javax.annotation.concurrent.GuardedBy;
351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/**
371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Adds computing functionality to {@link MapMakerInternalMap}.
381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author Bob Lee
401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author Charles Fry
411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */
421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertclass ComputingConcurrentHashMap<K, V> extends MapMakerInternalMap<K, V> {
431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  final Function<? super K, ? extends V> computingFunction;
441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Creates a new, empty map with the specified strategy, initial capacity, load factor and
471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * concurrency level.
481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  ComputingConcurrentHashMap(MapMaker builder,
501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      Function<? super K, ? extends V> computingFunction) {
511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    super(builder);
521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    this.computingFunction = checkNotNull(computingFunction);
531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Override
561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  Segment<K, V> createSegment(int initialCapacity, int maxSegmentSize) {
571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return new ComputingSegment<K, V>(this, initialCapacity, maxSegmentSize);
581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Override
611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  ComputingSegment<K, V> segmentFor(int hash) {
621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return (ComputingSegment<K, V>) super.segmentFor(hash);
631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  V getOrCompute(K key) throws ExecutionException {
661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int hash = hash(checkNotNull(key));
671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return segmentFor(hash).getOrCompute(key, hash, computingFunction);
681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @SuppressWarnings("serial") // This class is never serialized.
711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static final class ComputingSegment<K, V> extends Segment<K, V> {
721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ComputingSegment(MapMakerInternalMap<K, V> map, int initialCapacity, int maxSegmentSize) {
731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      super(map, initialCapacity, maxSegmentSize);
741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    V getOrCompute(K key, int hash, Function<? super K, ? extends V> computingFunction)
771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        throws ExecutionException {
781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      try {
791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        outer: while (true) {
801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          // don't call getLiveEntry, which would ignore computing values
811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          ReferenceEntry<K, V> e = getEntry(key, hash);
821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          if (e != null) {
831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            V value = getLiveValue(e);
841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            if (value != null) {
851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              recordRead(e);
861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              return value;
871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            }
881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          // at this point e is either null, computing, or expired;
911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          // avoid locking if it's already computing
921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          if (e == null || !e.getValueReference().isComputingReference()) {
931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            boolean createNewEntry = true;
941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            ComputingValueReference<K, V> computingValueReference = null;
951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            lock();
961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            try {
971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              preWriteCleanup();
981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              int newCount = this.count - 1;
1001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              AtomicReferenceArray<ReferenceEntry<K, V>> table = this.table;
1011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              int index = hash & (table.length() - 1);
1021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              ReferenceEntry<K, V> first = table.get(index);
1031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              for (e = first; e != null; e = e.getNext()) {
1051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                K entryKey = e.getKey();
1061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                if (e.getHash() == hash && entryKey != null
1071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                    && map.keyEquivalence.equivalent(key, entryKey)) {
1081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                  ValueReference<K, V> valueReference = e.getValueReference();
1091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                  if (valueReference.isComputingReference()) {
1101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                    createNewEntry = false;
1111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                  } else {
1121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                    V value = e.getValueReference().get();
1131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                    if (value == null) {
1141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                      enqueueNotification(entryKey, hash, value, RemovalCause.COLLECTED);
1151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                    } else if (map.expires() && map.isExpired(e)) {
1161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                      // This is a duplicate check, as preWriteCleanup already purged expired
1171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                      // entries, but let's accomodate an incorrect expiration queue.
1181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                      enqueueNotification(entryKey, hash, value, RemovalCause.EXPIRED);
1191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                    } else {
1201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                      recordLockedRead(e);
1211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                      return value;
1221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                    }
1231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                    // immediately reuse invalid entries
1251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                    evictionQueue.remove(e);
1261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                    expirationQueue.remove(e);
1271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                    this.count = newCount; // write-volatile
1281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                  }
1291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                  break;
1301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                }
1311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              }
1321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              if (createNewEntry) {
1341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                computingValueReference = new ComputingValueReference<K, V>(computingFunction);
1351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                if (e == null) {
1371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                  e = newEntry(key, hash, first);
1381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                  e.setValueReference(computingValueReference);
1391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                  table.set(index, e);
1401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                } else {
1411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                  e.setValueReference(computingValueReference);
1421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                }
1431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              }
1441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            } finally {
1451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              unlock();
1461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              postWriteCleanup();
1471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            }
1481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            if (createNewEntry) {
1501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              // This thread solely created the entry.
1511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              return compute(key, hash, e, computingValueReference);
1521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            }
1531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
1541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          // The entry already exists. Wait for the computation.
1561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          checkState(!Thread.holdsLock(e), "Recursive computation");
1571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          // don't consider expiration as we're concurrent with computation
1581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          V value = e.getValueReference().waitForValue();
1591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          if (value != null) {
1601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            recordRead(e);
1611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            return value;
1621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
1631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          // else computing thread will clearValue
1641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          continue outer;
1651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
1661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } finally {
1671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        postReadCleanup();
1681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
1691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    V compute(K key, int hash, ReferenceEntry<K, V> e,
1721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ComputingValueReference<K, V> computingValueReference)
1731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        throws ExecutionException {
1741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      V value = null;
1751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      long start = System.nanoTime();
1761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      long end = 0;
1771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      try {
1781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        // Synchronizes on the entry to allow failing fast when a recursive computation is
1791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        // detected. This is not fool-proof since the entry may be copied when the segment
1801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        // is written to.
1811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        synchronized (e) {
1821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          value = computingValueReference.compute(key, hash);
1831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          end = System.nanoTime();
1841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
1851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (value != null) {
1861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          // putIfAbsent
1871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          V oldValue = put(key, hash, value, true);
1881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          if (oldValue != null) {
1891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            // the computed value was already clobbered
1901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            enqueueNotification(key, hash, value, RemovalCause.REPLACED);
1911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
1921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
1931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return value;
1941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } finally {
1951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (end == 0) {
1961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          end = System.nanoTime();
1971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
1981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (value == null) {
1991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          clearValue(key, hash, computingValueReference);
2001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
2011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
2021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
2061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Used to provide computation exceptions to other threads.
2071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
2081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static final class ComputationExceptionReference<K, V> implements ValueReference<K, V> {
2091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final Throwable t;
2101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ComputationExceptionReference(Throwable t) {
2121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.t = t;
2131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
2161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public V get() {
2171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return null;
2181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
2211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ReferenceEntry<K, V> getEntry() {
2221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return null;
2231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
2261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ValueReference<K, V> copyFor(ReferenceQueue<V> queue, ReferenceEntry<K, V> entry) {
2271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return this;
2281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
2311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public boolean isComputingReference() {
2321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return false;
2331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
2361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public V waitForValue() throws ExecutionException {
2371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new ExecutionException(t);
2381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
2411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void clear(ValueReference<K, V> newValue) {}
2421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
2451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Used to provide computation result to other threads.
2461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
2471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static final class ComputedReference<K, V> implements ValueReference<K, V> {
2481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final V value;
2491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ComputedReference(@Nullable V value) {
2511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.value = value;
2521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
2551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public V get() {
2561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return value;
2571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
2601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ReferenceEntry<K, V> getEntry() {
2611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return null;
2621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
2651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ValueReference<K, V> copyFor(ReferenceQueue<V> queue, ReferenceEntry<K, V> entry) {
2661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return this;
2671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
2701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public boolean isComputingReference() {
2711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return false;
2721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
2751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public V waitForValue() {
2761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return get();
2771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
2801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void clear(ValueReference<K, V> newValue) {}
2811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static final class ComputingValueReference<K, V> implements ValueReference<K, V> {
2841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final Function<? super K, ? extends V> computingFunction;
2851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @GuardedBy("ComputingValueReference.this") // writes
2871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    volatile ValueReference<K, V> computedReference = unset();
2881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ComputingValueReference(Function<? super K, ? extends V> computingFunction) {
2901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.computingFunction = computingFunction;
2911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
2941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public V get() {
2951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // All computation lookups go through waitForValue. This method thus is
2961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // only used by put, to whom we always want to appear absent.
2971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return null;
2981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
3011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ReferenceEntry<K, V> getEntry() {
3021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return null;
3031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
3061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ValueReference<K, V> copyFor(ReferenceQueue<V> queue, ReferenceEntry<K, V> entry) {
3071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return this;
3081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
3111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public boolean isComputingReference() {
3121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return true;
3131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
3161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Waits for a computation to complete. Returns the result of the computation.
3171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
3181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
3191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public V waitForValue() throws ExecutionException {
3201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (computedReference == UNSET) {
3211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        boolean interrupted = false;
3221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        try {
3231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          synchronized (this) {
3241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            while (computedReference == UNSET) {
3251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              try {
3261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                wait();
3271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              } catch (InterruptedException ie) {
3281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                interrupted = true;
3291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              }
3301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            }
3311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
3321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        } finally {
3331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          if (interrupted) {
3341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            Thread.currentThread().interrupt();
3351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
3361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
3371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
3381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return computedReference.waitForValue();
3391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
3421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void clear(ValueReference<K, V> newValue) {
3431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // The pending computation was clobbered by a manual write. Unblock all
3441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // pending gets, and have them return the new value.
3451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      setValueReference(newValue);
3461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // TODO(fry): could also cancel computation if we had a thread handle
3481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    V compute(K key, int hash) throws ExecutionException {
3511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      V value;
3521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      try {
3531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        value = computingFunction.apply(key);
3541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } catch (Throwable t) {
3551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        setValueReference(new ComputationExceptionReference<K, V>(t));
3561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        throw new ExecutionException(t);
3571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
3581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      setValueReference(new ComputedReference<K, V>(value));
3601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return value;
3611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    void setValueReference(ValueReference<K, V> valueReference) {
3641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      synchronized (this) {
3651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (computedReference == UNSET) {
3661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          computedReference = valueReference;
3671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          notifyAll();
3681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
3691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
3701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  // Serialization Support
3741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static final long serialVersionUID = 4;
3761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Override
3781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  Object writeReplace() {
3791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return new ComputingSerializationProxy<K, V>(keyStrength, valueStrength, keyEquivalence,
3801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        valueEquivalence, expireAfterWriteNanos, expireAfterAccessNanos, maximumSize,
3811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        concurrencyLevel, removalListener, this, computingFunction);
3821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static final class ComputingSerializationProxy<K, V> extends AbstractSerializationProxy<K, V> {
3851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final Function<? super K, ? extends V> computingFunction;
3871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ComputingSerializationProxy(Strength keyStrength, Strength valueStrength,
3891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        Equivalence<Object> keyEquivalence, Equivalence<Object> valueEquivalence,
3901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        long expireAfterWriteNanos, long expireAfterAccessNanos, int maximumSize,
3911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        int concurrencyLevel, RemovalListener<? super K, ? super V> removalListener,
3921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ConcurrentMap<K, V> delegate, Function<? super K, ? extends V> computingFunction) {
3931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      super(keyStrength, valueStrength, keyEquivalence, valueEquivalence, expireAfterWriteNanos,
3941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          expireAfterAccessNanos, maximumSize, concurrencyLevel, removalListener, delegate);
3951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.computingFunction = computingFunction;
3961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private void writeObject(ObjectOutputStream out) throws IOException {
3991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      out.defaultWriteObject();
4001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      writeMapTo(out);
4011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
4021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @SuppressWarnings("deprecation") // self-use
4041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
4051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      in.defaultReadObject();
4061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      MapMaker mapMaker = readMapMaker(in);
4071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      delegate = mapMaker.makeComputingMap(computingFunction);
4081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      readEntries(in);
4091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
4101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Object readResolve() {
4121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return delegate;
4131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
4141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private static final long serialVersionUID = 4;
4161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
4171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
418