11d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// Copyright 2011 Google Inc. All Rights Reserved.
21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
31d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpackage com.google.common.util.concurrent;
41d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
51d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.base.Preconditions.checkNotNull;
61d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
71d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.annotations.Beta;
81d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.base.Function;
91d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.collect.Maps;
101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Collections;
121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Map;
131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.ConcurrentHashMap;
141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.atomic.AtomicLong;
151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/**
171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * A map containing {@code long} values that can be atomically updated. While writes to a
181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * traditional {@code Map} rely on {@code put(K, V)}, the typical mechanism for writing to this map
191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * is {@code addAndGet(K, long)}, which adds a {@code long} to the value currently associated with
201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@code K}. If a key has not yet been associated with a value, its implicit value is zero.
211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>Most methods in this class treat absent values and zero values identically, as individually
231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * documented. Exceptions to this are {@link #containsKey}, {@link #size}, {@link #isEmpty},
241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link #asMap}, and {@link #toString}.
251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>Instances of this class may be used by multiple threads concurrently. All operations are
271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * atomic unless otherwise noted.
281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p><b>Note:</b> If your values are always positive and less than 2^31, you may wish to use a
301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link com.google.common.collect.Multiset} such as
311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link com.google.common.collect.ConcurrentHashMultiset} instead.
321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <b>Warning:</b> Unlike {@code Multiset}, entries whose values are zero are not automatically
341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * removed from the map. Instead they must be removed manually with {@link #removeAllZeros}.
351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author Charles Fry
371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @since 11.0
381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */
391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert@Beta
401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpublic final class AtomicLongMap<K> {
411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private final ConcurrentHashMap<K, AtomicLong> map;
421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private AtomicLongMap(ConcurrentHashMap<K, AtomicLong> map) {
441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    this.map = checkNotNull(map);
451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Creates an {@code AtomicLongMap}.
491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public static <K> AtomicLongMap<K> create() {
511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return new AtomicLongMap<K>(new ConcurrentHashMap<K, AtomicLong>());
521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Creates an {@code AtomicLongMap} with the same mappings as the specified {@code Map}.
561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public static <K> AtomicLongMap<K> create(Map<? extends K, ? extends Long> m) {
581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    AtomicLongMap<K> result = create();
591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    result.putAll(m);
601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return result;
611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns the value associated with {@code key}, or zero if there is no value associated with
651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * {@code key}.
661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public long get(K key) {
681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    AtomicLong atomic = map.get(key);
691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return atomic == null ? 0L : atomic.get();
701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Increments by one the value currently associated with {@code key}, and returns the new value.
741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public long incrementAndGet(K key) {
761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return addAndGet(key, 1);
771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Decrements by one the value currently associated with {@code key}, and returns the new value.
811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public long decrementAndGet(K key) {
831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return addAndGet(key, -1);
841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Adds {@code delta} to the value currently associated with {@code key}, and returns the new
881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * value.
891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public long addAndGet(K key, long delta) {
911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    outer: for (;;) {
921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      AtomicLong atomic = map.get(key);
931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (atomic == null) {
941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        atomic = map.putIfAbsent(key, new AtomicLong(delta));
951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (atomic == null) {
961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return delta;
971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        // atomic is now non-null; fall through
991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
1001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      for (;;) {
1021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        long oldValue = atomic.get();
1031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (oldValue == 0L) {
1041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          // don't compareAndSet a zero
1051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          if (map.replace(key, atomic, new AtomicLong(delta))) {
1061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            return delta;
1071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
1081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          // atomic replaced
1091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          continue outer;
1101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
1111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        long newValue = oldValue + delta;
1131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (atomic.compareAndSet(oldValue, newValue)) {
1141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return newValue;
1151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
1161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        // value changed
1171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
1181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
1221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Increments by one the value currently associated with {@code key}, and returns the old value.
1231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public long getAndIncrement(K key) {
1251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return getAndAdd(key, 1);
1261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
1291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Decrements by one the value currently associated with {@code key}, and returns the old value.
1301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public long getAndDecrement(K key) {
1321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return getAndAdd(key, -1);
1331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
1361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Adds {@code delta} to the value currently associated with {@code key}, and returns the old
1371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * value.
1381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public long getAndAdd(K key, long delta) {
1401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    outer: for (;;) {
1411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      AtomicLong atomic = map.get(key);
1421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (atomic == null) {
1431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        atomic = map.putIfAbsent(key, new AtomicLong(delta));
1441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (atomic == null) {
1451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return 0L;
1461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
1471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        // atomic is now non-null; fall through
1481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
1491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      for (;;) {
1511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        long oldValue = atomic.get();
1521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (oldValue == 0L) {
1531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          // don't compareAndSet a zero
1541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          if (map.replace(key, atomic, new AtomicLong(delta))) {
1551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            return 0L;
1561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
1571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          // atomic replaced
1581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          continue outer;
1591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
1601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        long newValue = oldValue + delta;
1621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (atomic.compareAndSet(oldValue, newValue)) {
1631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return oldValue;
1641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
1651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        // value changed
1661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
1671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
1711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Associates {@code newValue} with {@code key} in this map, and returns the value previously
1721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * associated with {@code key}, or zero if there was no such value.
1731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public long put(K key, long newValue) {
1751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    outer: for (;;) {
1761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      AtomicLong atomic = map.get(key);
1771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (atomic == null) {
1781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        atomic = map.putIfAbsent(key, new AtomicLong(newValue));
1791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (atomic == null) {
1801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return 0L;
1811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
1821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        // atomic is now non-null; fall through
1831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
1841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      for (;;) {
1861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        long oldValue = atomic.get();
1871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (oldValue == 0L) {
1881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          // don't compareAndSet a zero
1891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          if (map.replace(key, atomic, new AtomicLong(newValue))) {
1901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            return 0L;
1911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
1921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          // atomic replaced
1931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          continue outer;
1941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
1951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (atomic.compareAndSet(oldValue, newValue)) {
1971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return oldValue;
1981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
1991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        // value changed
2001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
2011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
2051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Copies all of the mappings from the specified map to this map. The effect of this call is
2061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * equivalent to that of calling {@code put(k, v)} on this map once for each mapping from key
2071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * {@code k} to value {@code v} in the specified map. The behavior of this operation is undefined
2081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * if the specified map is modified while the operation is in progress.
2091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
2101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void putAll(Map<? extends K, ? extends Long> m) {
2111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (Map.Entry<? extends K, ? extends Long> entry : m.entrySet()) {
2121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      put(entry.getKey(), entry.getValue());
2131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
2171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Removes and returns the value associated with {@code key}. If {@code key} is not
2181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * in the map, this method has no effect and returns zero.
2191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
2201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public long remove(K key) {
2211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    AtomicLong atomic = map.get(key);
2221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (atomic == null) {
2231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return 0L;
2241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (;;) {
2271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      long oldValue = atomic.get();
2281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (oldValue == 0L || atomic.compareAndSet(oldValue, 0L)) {
2291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        // only remove after setting to zero, to avoid concurrent updates
2301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        map.remove(key, atomic);
2311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        // succeed even if the remove fails, since the value was already adjusted
2321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return oldValue;
2331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
2341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
2381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Removes all mappings from this map whose values are zero.
2391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
2401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>This method is not atomic: the map may be visible in intermediate states, where some
2411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * of the zero values have been removed and others have not.
2421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
2431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void removeAllZeros() {
2441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (K key : map.keySet()) {
2451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      AtomicLong atomic = map.get(key);
2461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (atomic != null && atomic.get() == 0L) {
2471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        map.remove(key, atomic);
2481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
2491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
2531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns the sum of all values in this map.
2541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
2551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>This method is not atomic: the sum may or may not include other concurrent operations.
2561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
2571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public long sum() {
2581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    long sum = 0L;
2591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (AtomicLong value : map.values()) {
2601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      sum = sum + value.get();
2611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return sum;
2631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private transient Map<K, Long> asMap;
2661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
2681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns a live, read-only view of the map backing this {@code AtomicLongMap}.
2691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
2701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public Map<K, Long> asMap() {
2711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Map<K, Long> result = asMap;
2721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return (result == null) ? asMap = createAsMap() : result;
2731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private Map<K, Long> createAsMap() {
2761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return Collections.unmodifiableMap(
2771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        Maps.transformValues(map, new Function<AtomicLong, Long>() {
2781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          @Override
2791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          public Long apply(AtomicLong atomic) {
2801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            return atomic.get();
2811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
2821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }));
2831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
2861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns true if this map contains a mapping for the specified key.
2871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
2881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public boolean containsKey(Object key) {
2891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return map.containsKey(key);
2901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
2931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns the number of key-value mappings in this map. If the map contains more than
2941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * {@code Integer.MAX_VALUE} elements, returns {@code Integer.MAX_VALUE}.
2951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
2961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public int size() {
2971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return map.size();
2981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
3011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns {@code true} if this map contains no key-value mappings.
3021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
3031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public boolean isEmpty() {
3041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return map.isEmpty();
3051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
3081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Removes all of the mappings from this map. The map will be empty after this call returns.
3091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
3101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>This method is not atomic: the map may not be empty after returning if there were concurrent
3111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * writes.
3121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
3131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void clear() {
3141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    map.clear();
3151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Override
3181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public String toString() {
3191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return map.toString();
3201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /*
3231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * ConcurrentMap operations which we may eventually add.
3241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
3251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * The problem with these is that remove(K, long) has to be done in two phases by definition ---
3261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * first decrementing to zero, and then removing. putIfAbsent or replace could observe the
3271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * intermediate zero-state. Ways we could deal with this are:
3281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
3291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * - Don't define any of the ConcurrentMap operations. This is the current state of affairs.
3301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
3311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * - Define putIfAbsent and replace as treating zero and absent identically (as currently
3321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *   implemented below). This is a bit surprising with putIfAbsent, which really becomes
3331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *   putIfZero.
3341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
3351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * - Allow putIfAbsent and replace to distinguish between zero and absent, but don't implement
3361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *   remove(K, long). Without any two-phase operations it becomes feasible for all remaining
3371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *   operations to distinguish between zero and absent. If we do this, then perhaps we should add
3381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *   replace(key, long).
3391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
3401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * - Introduce a special-value private static final AtomicLong that would have the meaning of
3411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *   removal-in-progress, and rework all operations to properly distinguish between zero and
3421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *   absent.
3431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
3441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
3461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * If {@code key} is not already associated with a value or if {@code key} is associated with
3471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * zero, associate it with {@code newValue}. Returns the previous value associated with
3481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * {@code key}, or zero if there was no mapping for {@code key}.
3491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
3501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  long putIfAbsent(K key, long newValue) {
3511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (;;) {
3521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      AtomicLong atomic = map.get(key);
3531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (atomic == null) {
3541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        atomic = map.putIfAbsent(key, new AtomicLong(newValue));
3551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (atomic == null) {
3561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return 0L;
3571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
3581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        // atomic is now non-null; fall through
3591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
3601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      long oldValue = atomic.get();
3621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (oldValue == 0L) {
3631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        // don't compareAndSet a zero
3641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (map.replace(key, atomic, new AtomicLong(newValue))) {
3651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return 0L;
3661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
3671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        // atomic replaced
3681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        continue;
3691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
3701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return oldValue;
3721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
3761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * If {@code (key, expectedOldValue)} is currently in the map, this method replaces
3771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * {@code expectedOldValue} with {@code newValue} and returns true; otherwise, this method
3781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * returns false.
3791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
3801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>If {@code expectedOldValue} is zero, this method will succeed if {@code (key, zero)}
3811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * is currently in the map, or if {@code key} is not in the map at all.
3821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
3831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  boolean replace(K key, long expectedOldValue, long newValue) {
3841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (expectedOldValue == 0L) {
3851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return putIfAbsent(key, newValue) == 0L;
3861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } else {
3871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      AtomicLong atomic = map.get(key);
3881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return (atomic == null) ? false : atomic.compareAndSet(expectedOldValue, newValue);
3891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
3931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * If {@code (key, value)} is currently in the map, this method removes it and returns
3941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * true; otherwise, this method returns false.
3951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
3961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  boolean remove(K key, long value) {
3971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    AtomicLong atomic = map.get(key);
3981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (atomic == null) {
3991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return false;
4001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
4011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    long oldValue = atomic.get();
4031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (oldValue != value) {
4041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return false;
4051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
4061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (oldValue == 0L || atomic.compareAndSet(oldValue, 0L)) {
4081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // only remove after setting to zero, to avoid concurrent updates
4091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      map.remove(key, atomic);
4101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // succeed even if the remove fails, since the value was already adjusted
4111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return true;
4121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
4131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // value changed
4151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return false;
4161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
4171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
419