Java Code Examples for java.util.concurrent.ConcurrentMap#replace()

The following examples show how to use java.util.concurrent.ConcurrentMap#replace() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: ConcurrentMetricCounters.java    From jenkins-datadog-plugin with MIT License 6 votes vote down vote up
public synchronized void increment(String name, String hostname, Map<String, Set<String>> tags) {
    ConcurrentMap<CounterMetric, Integer> counters = ConcurrentMetricCounters.get();
    CounterMetric counterMetric = new CounterMetric(tags, name, hostname);
    Integer previousValue = counters.putIfAbsent(counterMetric, 1);
    if (previousValue != null){
        boolean ok = counters.replace(counterMetric, previousValue, previousValue + 1);
        // NOTE:
        // This while loop below should never be called since we are using a lock when flushing and
        // incrementing counters.
        while(!ok) {
            logger.warning("Couldn't increment counter " + name + " with value " + (previousValue + 1) +
                    " previousValue = " + previousValue);
            previousValue = counters.get(counterMetric);
            ok = counters.replace(counterMetric, previousValue, previousValue + 1);
        }
    }
    previousValue = previousValue == null ? 0 : previousValue;
    logger.fine("Counter " + name + " updated from previousValue " + previousValue + " to "
            + (previousValue + 1));
}
 
Example 2
Source File: Bug2898106a.java    From spotbugs with GNU Lesser General Public License v2.1 6 votes vote down vote up
static Semaphore getLock(ConcurrentMap<String, Semaphore> locks2, String key) {
    Semaphore lock = locks2.get(key);
    if (lock == null) {
        Semaphore newLock = new Semaphore(1, true);
        locks2.get(null);
        locks2.put(null, null);
        locks2.remove(null);
        locks2.containsKey(null);
        locks2.containsValue(null);
        locks2.putIfAbsent(null, null);
        locks2.remove(null, null);
        locks2.replace(null, null);
        locks2.replace(null, null, null);
        lock = locks2.putIfAbsent(key, lock);
        // value, being null, will *always* throw NullPointerException
        if (lock == null)
            lock = newLock;
    }
    return lock;
}
 
Example 3
Source File: MarshallerContextImpl.java    From ignite with Apache License 2.0 5 votes vote down vote up
/**
 * @param item Item.
 */
public void onMappingAccepted(final MarshallerMappingItem item) {
    ConcurrentMap<Integer, MappedName> cache = getCacheFor(item.platformId());

    cache.replace(item.typeId(), new MappedName(item.className(), true));

    closProc.runLocalSafe(new MappingStoreTask(fileStore, item.platformId(), item.typeId(), item.className()));
}
 
Example 4
Source File: SequenceIdAccounting.java    From hbase with Apache License 2.0 5 votes vote down vote up
/**
 * Update the store sequence id, e.g., upon executing in-memory compaction
 */
void updateStore(byte[] encodedRegionName, byte[] familyName, Long sequenceId,
    boolean onlyIfGreater) {
  if (sequenceId == null) {
    return;
  }
  Long highest = this.highestSequenceIds.get(encodedRegionName);
  if (highest == null || sequenceId > highest) {
    this.highestSequenceIds.put(encodedRegionName, sequenceId);
  }
  ImmutableByteArray familyNameWrapper = ImmutableByteArray.wrap(familyName);
  synchronized (this.tieLock) {
    ConcurrentMap<ImmutableByteArray, Long> m = getOrCreateLowestSequenceIds(encodedRegionName);
    boolean replaced = false;
    while (!replaced) {
      Long oldSeqId = m.get(familyNameWrapper);
      if (oldSeqId == null) {
        m.put(familyNameWrapper, sequenceId);
        replaced = true;
      } else if (onlyIfGreater) {
        if (sequenceId > oldSeqId) {
          replaced = m.replace(familyNameWrapper, oldSeqId, sequenceId);
        } else {
          return;
        }
      } else { // replace even if sequence id is not greater than oldSeqId
        m.put(familyNameWrapper, sequenceId);
        return;
      }
    }
  }
}
 
Example 5
Source File: ConcurrentHashMapTest.java    From caffeine with Apache License 2.0 5 votes vote down vote up
/**
 * replace(x, null, y) throws NPE
 */
public void testReplaceValue2_NullPointerException() {
    ConcurrentMap c = map();
    try {
        c.replace("whatever", null, "A");
        shouldThrow();
    } catch (NullPointerException success) {}
}
 
Example 6
Source File: ConcurrentMapTest.java    From concurrentlinkedhashmap with Apache License 2.0 4 votes vote down vote up
@Test(dataProvider = "guardedMap", expectedExceptions = NullPointerException.class)
public void replaceConditionally_withNullKeyAndValues(ConcurrentMap<Integer, Integer> map) {
  map.replace(null, null, null);
}
 
Example 7
Source File: WeakCache.java    From jdk8u-jdk with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Look-up the value through the cache. This always evaluates the
 * {@code subKeyFactory} function and optionally evaluates
 * {@code valueFactory} function if there is no entry in the cache for given
 * pair of (key, subKey) or the entry has already been cleared.
 *
 * @param key       possibly null key
 * @param parameter parameter used together with key to create sub-key and
 *                  value (should not be null)
 * @return the cached value (never null)
 * @throws NullPointerException if {@code parameter} passed in or
 *                              {@code sub-key} calculated by
 *                              {@code subKeyFactory} or {@code value}
 *                              calculated by {@code valueFactory} is null.
 */
public V get(K key, P parameter) {
    Objects.requireNonNull(parameter);

    expungeStaleEntries();

    Object cacheKey = CacheKey.valueOf(key, refQueue);

    // lazily install the 2nd level valuesMap for the particular cacheKey
    ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);
    if (valuesMap == null) {
        ConcurrentMap<Object, Supplier<V>> oldValuesMap
            = map.putIfAbsent(cacheKey,
                              valuesMap = new ConcurrentHashMap<>());
        if (oldValuesMap != null) {
            valuesMap = oldValuesMap;
        }
    }

    // create subKey and retrieve the possible Supplier<V> stored by that
    // subKey from valuesMap
    Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
    Supplier<V> supplier = valuesMap.get(subKey);
    Factory factory = null;

    while (true) {
        if (supplier != null) {
            // supplier might be a Factory or a CacheValue<V> instance
            V value = supplier.get();
            if (value != null) {
                return value;
            }
        }
        // else no supplier in cache
        // or a supplier that returned null (could be a cleared CacheValue
        // or a Factory that wasn't successful in installing the CacheValue)

        // lazily construct a Factory
        if (factory == null) {
            factory = new Factory(key, parameter, subKey, valuesMap);
        }

        if (supplier == null) {
            supplier = valuesMap.putIfAbsent(subKey, factory);
            if (supplier == null) {
                // successfully installed Factory
                supplier = factory;
            }
            // else retry with winning supplier
        } else {
            if (valuesMap.replace(subKey, supplier, factory)) {
                // successfully replaced
                // cleared CacheEntry / unsuccessful Factory
                // with our Factory
                supplier = factory;
            } else {
                // retry with current supplier
                supplier = valuesMap.get(subKey);
            }
        }
    }
}
 
Example 8
Source File: ConcurrentMaps.java    From streamsupport with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Attempts to compute a mapping for the specified key and its current
 * mapped value (or {@code null} if there is no current mapping). For
 * example, to either create or append a {@code String} msg to a value
 * mapping:
 *
 * <pre> {@code
 * map.compute(key, (k, v) -> (v == null) ? msg : v.concat(msg))}</pre>
 * (Method {@link #merge merge()} is often simpler to use for such purposes.)
 *
 * <p>If the remapping function returns {@code null}, the mapping is removed
 * (or remains absent if initially absent).  If the remapping function itself
 * throws an (unchecked) exception, the exception is rethrown, and the current
 * mapping is left unchanged.
 *
 * <p>The remapping function itself should not modify the passed map during
 * computation.
 *
 * <p><b>Implementation Requirements:</b><br>
 * The default implementation is equivalent to performing the following
 * steps for the {@code map}:
 *
 * <pre> {@code
 * for (;;) {
 *   V oldValue = map.get(key);
 *   V newValue = remappingFunction.apply(key, oldValue);
 *   if (newValue != null) {
 *     if ((oldValue != null)
 *       ? map.replace(key, oldValue, newValue)
 *       : map.putIfAbsent(key, newValue) == null)
 *       return newValue;
 *   } else if (oldValue == null || map.remove(key, oldValue)) {
 *     return null;
 *   }
 * }}</pre>
 * When multiple threads attempt updates, map operations and the
 * remapping function may be called multiple times.
 *
 * <p>This implementation assumes that the ConcurrentMap cannot contain null
 * values and {@code get()} returning null unambiguously means the key is
 * absent. Implementations which support null values <strong>must</strong>
 * override this default implementation.
 *
 * @param <K> the type of keys maintained by the passed map
 * @param <V> the type of mapped values in the passed map
 * @param map the {@code ConcurrentMap} on which to execute the {@code compute}
 * operation.
 * @param key key with which the specified value is to be associated
 * @param remappingFunction the remapping function to compute a value
 * @return the new value associated with the specified key, or null if none
 * @throws NullPointerException if the specified key is null and
 *         the map does not support null keys, or the
 *         remappingFunction is null
 * @throws UnsupportedOperationException if the {@code put} operation
 *         is not supported by the map (optional)
 * @throws ClassCastException if the class of the specified key or value
 *         prevents it from being stored in the map (optional)
 * @throws IllegalArgumentException if some property of the specified key
 *         or value prevents it from being stored in this map (optional)
 * @since 1.8
 */
public static <K, V> V compute(ConcurrentMap<K, V> map, K key,
        BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
    Objects.requireNonNull(map);
    retry: for (;;) {
        V oldValue = map.get(key);
        // if putIfAbsent fails, opportunistically use its return value
        haveOldValue: for (;;) {
            V newValue = remappingFunction.apply(key, oldValue);
            if (newValue != null) {
                if (oldValue != null) {
                    if (map.replace(key, oldValue, newValue))
                        return newValue;
                }
                else if ((oldValue = map.putIfAbsent(key, newValue)) == null)
                    return newValue;
                else continue haveOldValue;
            } else if (oldValue == null || map.remove(key, oldValue)) {
                return null;
            }
            continue retry;
        }
    }
}
 
Example 9
Source File: ConcurrentMapTest.java    From concurrentlinkedhashmap with Apache License 2.0 4 votes vote down vote up
@Test(dataProvider = "guardedMap", expectedExceptions = NullPointerException.class)
public void replaceConditionally_withNullKeyAndNewValue(ConcurrentMap<Integer, Integer> map) {
  map.replace(null, 2, null);
}
 
Example 10
Source File: ConcurrentMapTest.java    From concurrentlinkedhashmap with Apache License 2.0 4 votes vote down vote up
@Test(dataProvider = "guardedMap", expectedExceptions = NullPointerException.class)
public void replaceConditionally_withNullNewValue(ConcurrentMap<Integer, Integer> map) {
  map.replace(1, 2, null);
}
 
Example 11
Source File: WeakCache.java    From jdk8u_jdk with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Look-up the value through the cache. This always evaluates the
 * {@code subKeyFactory} function and optionally evaluates
 * {@code valueFactory} function if there is no entry in the cache for given
 * pair of (key, subKey) or the entry has already been cleared.
 *
 * @param key       possibly null key
 * @param parameter parameter used together with key to create sub-key and
 *                  value (should not be null)
 * @return the cached value (never null)
 * @throws NullPointerException if {@code parameter} passed in or
 *                              {@code sub-key} calculated by
 *                              {@code subKeyFactory} or {@code value}
 *                              calculated by {@code valueFactory} is null.
 */
public V get(K key, P parameter) {
    Objects.requireNonNull(parameter);

    expungeStaleEntries();

    Object cacheKey = CacheKey.valueOf(key, refQueue);

    // lazily install the 2nd level valuesMap for the particular cacheKey
    ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);
    if (valuesMap == null) {
        ConcurrentMap<Object, Supplier<V>> oldValuesMap
            = map.putIfAbsent(cacheKey,
                              valuesMap = new ConcurrentHashMap<>());
        if (oldValuesMap != null) {
            valuesMap = oldValuesMap;
        }
    }

    // create subKey and retrieve the possible Supplier<V> stored by that
    // subKey from valuesMap
    Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
    Supplier<V> supplier = valuesMap.get(subKey);
    Factory factory = null;

    while (true) {
        if (supplier != null) {
            // supplier might be a Factory or a CacheValue<V> instance
            V value = supplier.get();
            if (value != null) {
                return value;
            }
        }
        // else no supplier in cache
        // or a supplier that returned null (could be a cleared CacheValue
        // or a Factory that wasn't successful in installing the CacheValue)

        // lazily construct a Factory
        if (factory == null) {
            factory = new Factory(key, parameter, subKey, valuesMap);
        }

        if (supplier == null) {
            supplier = valuesMap.putIfAbsent(subKey, factory);
            if (supplier == null) {
                // successfully installed Factory
                supplier = factory;
            }
            // else retry with winning supplier
        } else {
            if (valuesMap.replace(subKey, supplier, factory)) {
                // successfully replaced
                // cleared CacheEntry / unsuccessful Factory
                // with our Factory
                supplier = factory;
            } else {
                // retry with current supplier
                supplier = valuesMap.get(subKey);
            }
        }
    }
}
 
Example 12
Source File: WeakCache.java    From openjdk-8-source with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Look-up the value through the cache. This always evaluates the
 * {@code subKeyFactory} function and optionally evaluates
 * {@code valueFactory} function if there is no entry in the cache for given
 * pair of (key, subKey) or the entry has already been cleared.
 *
 * @param key       possibly null key
 * @param parameter parameter used together with key to create sub-key and
 *                  value (should not be null)
 * @return the cached value (never null)
 * @throws NullPointerException if {@code parameter} passed in or
 *                              {@code sub-key} calculated by
 *                              {@code subKeyFactory} or {@code value}
 *                              calculated by {@code valueFactory} is null.
 */
public V get(K key, P parameter) {
    Objects.requireNonNull(parameter);

    expungeStaleEntries();

    Object cacheKey = CacheKey.valueOf(key, refQueue);

    // lazily install the 2nd level valuesMap for the particular cacheKey
    ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);
    if (valuesMap == null) {
        ConcurrentMap<Object, Supplier<V>> oldValuesMap
            = map.putIfAbsent(cacheKey,
                              valuesMap = new ConcurrentHashMap<>());
        if (oldValuesMap != null) {
            valuesMap = oldValuesMap;
        }
    }

    // create subKey and retrieve the possible Supplier<V> stored by that
    // subKey from valuesMap
    Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
    Supplier<V> supplier = valuesMap.get(subKey);
    Factory factory = null;

    while (true) {
        if (supplier != null) {
            // supplier might be a Factory or a CacheValue<V> instance
            V value = supplier.get();
            if (value != null) {
                return value;
            }
        }
        // else no supplier in cache
        // or a supplier that returned null (could be a cleared CacheValue
        // or a Factory that wasn't successful in installing the CacheValue)

        // lazily construct a Factory
        if (factory == null) {
            factory = new Factory(key, parameter, subKey, valuesMap);
        }

        if (supplier == null) {
            supplier = valuesMap.putIfAbsent(subKey, factory);
            if (supplier == null) {
                // successfully installed Factory
                supplier = factory;
            }
            // else retry with winning supplier
        } else {
            if (valuesMap.replace(subKey, supplier, factory)) {
                // successfully replaced
                // cleared CacheEntry / unsuccessful Factory
                // with our Factory
                supplier = factory;
            } else {
                // retry with current supplier
                supplier = valuesMap.get(subKey);
            }
        }
    }
}
 
Example 13
Source File: CacheBuilderGwtTest.java    From caffeine with Apache License 2.0 4 votes vote down vote up
public void testMapMethods() {
  Cache<Integer, Integer> cache = CaffeinatedGuava.build(Caffeine.newBuilder());

  ConcurrentMap<Integer, Integer> asMap = cache.asMap();

  cache.put(10, 100);
  cache.put(2, 52);

  asMap.replace(2, 79);
  asMap.replace(3, 60);

  assertEquals(null, cache.getIfPresent(3));
  assertEquals(null, asMap.get(3));

  assertEquals(Integer.valueOf(79), cache.getIfPresent(2));
  assertEquals(Integer.valueOf(79), asMap.get(2));

  asMap.replace(10, 100, 50);
  asMap.replace(2, 52, 99);

  assertEquals(Integer.valueOf(50), cache.getIfPresent(10));
  assertEquals(Integer.valueOf(50), asMap.get(10));
  assertEquals(Integer.valueOf(79), cache.getIfPresent(2));
  assertEquals(Integer.valueOf(79), asMap.get(2));

  asMap.remove(10, 100);
  asMap.remove(2, 79);

  assertEquals(Integer.valueOf(50), cache.getIfPresent(10));
  assertEquals(Integer.valueOf(50), asMap.get(10));
  assertEquals(null, cache.getIfPresent(2));
  assertEquals(null, asMap.get(2));

  asMap.putIfAbsent(2, 20);
  asMap.putIfAbsent(10, 20);

  assertEquals(Integer.valueOf(20), cache.getIfPresent(2));
  assertEquals(Integer.valueOf(20), asMap.get(2));
  assertEquals(Integer.valueOf(50), cache.getIfPresent(10));
  assertEquals(Integer.valueOf(50), asMap.get(10));
}
 
Example 14
Source File: WeakCache.java    From Java8CN with Apache License 2.0 4 votes vote down vote up
/**
 * Look-up the value through the cache. This always evaluates the
 * {@code subKeyFactory} function and optionally evaluates
 * {@code valueFactory} function if there is no entry in the cache for given
 * pair of (key, subKey) or the entry has already been cleared.
 *
 * @param key       possibly null key
 * @param parameter parameter used together with key to create sub-key and
 *                  value (should not be null)
 * @return the cached value (never null)
 * @throws NullPointerException if {@code parameter} passed in or
 *                              {@code sub-key} calculated by
 *                              {@code subKeyFactory} or {@code value}
 *                              calculated by {@code valueFactory} is null.
 */
public V get(K key, P parameter) {
    Objects.requireNonNull(parameter);

    expungeStaleEntries();

    Object cacheKey = CacheKey.valueOf(key, refQueue);

    // lazily install the 2nd level valuesMap for the particular cacheKey
    ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);
    if (valuesMap == null) {
        ConcurrentMap<Object, Supplier<V>> oldValuesMap
            = map.putIfAbsent(cacheKey,
                              valuesMap = new ConcurrentHashMap<>());
        if (oldValuesMap != null) {
            valuesMap = oldValuesMap;
        }
    }

    // create subKey and retrieve the possible Supplier<V> stored by that
    // subKey from valuesMap
    Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
    Supplier<V> supplier = valuesMap.get(subKey);
    Factory factory = null;

    while (true) {
        if (supplier != null) {
            // supplier might be a Factory or a CacheValue<V> instance
            V value = supplier.get();
            if (value != null) {
                return value;
            }
        }
        // else no supplier in cache
        // or a supplier that returned null (could be a cleared CacheValue
        // or a Factory that wasn't successful in installing the CacheValue)

        // lazily construct a Factory
        if (factory == null) {
            factory = new Factory(key, parameter, subKey, valuesMap);
        }

        if (supplier == null) {
            supplier = valuesMap.putIfAbsent(subKey, factory);
            if (supplier == null) {
                // successfully installed Factory
                supplier = factory;
            }
            // else retry with winning supplier
        } else {
            if (valuesMap.replace(subKey, supplier, factory)) {
                // successfully replaced
                // cleared CacheEntry / unsuccessful Factory
                // with our Factory
                supplier = factory;
            } else {
                // retry with current supplier
                supplier = valuesMap.get(subKey);
            }
        }
    }
}
 
Example 15
Source File: WeakCache.java    From jdk8u-jdk with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Look-up the value through the cache. This always evaluates the
 * {@code subKeyFactory} function and optionally evaluates
 * {@code valueFactory} function if there is no entry in the cache for given
 * pair of (key, subKey) or the entry has already been cleared.
 *
 * @param key       possibly null key
 * @param parameter parameter used together with key to create sub-key and
 *                  value (should not be null)
 * @return the cached value (never null)
 * @throws NullPointerException if {@code parameter} passed in or
 *                              {@code sub-key} calculated by
 *                              {@code subKeyFactory} or {@code value}
 *                              calculated by {@code valueFactory} is null.
 */
public V get(K key, P parameter) {
    Objects.requireNonNull(parameter);

    expungeStaleEntries();

    Object cacheKey = CacheKey.valueOf(key, refQueue);

    // lazily install the 2nd level valuesMap for the particular cacheKey
    ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);
    if (valuesMap == null) {
        ConcurrentMap<Object, Supplier<V>> oldValuesMap
            = map.putIfAbsent(cacheKey,
                              valuesMap = new ConcurrentHashMap<>());
        if (oldValuesMap != null) {
            valuesMap = oldValuesMap;
        }
    }

    // create subKey and retrieve the possible Supplier<V> stored by that
    // subKey from valuesMap
    Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
    Supplier<V> supplier = valuesMap.get(subKey);
    Factory factory = null;

    while (true) {
        if (supplier != null) {
            // supplier might be a Factory or a CacheValue<V> instance
            V value = supplier.get();
            if (value != null) {
                return value;
            }
        }
        // else no supplier in cache
        // or a supplier that returned null (could be a cleared CacheValue
        // or a Factory that wasn't successful in installing the CacheValue)

        // lazily construct a Factory
        if (factory == null) {
            factory = new Factory(key, parameter, subKey, valuesMap);
        }

        if (supplier == null) {
            supplier = valuesMap.putIfAbsent(subKey, factory);
            if (supplier == null) {
                // successfully installed Factory
                supplier = factory;
            }
            // else retry with winning supplier
        } else {
            if (valuesMap.replace(subKey, supplier, factory)) {
                // successfully replaced
                // cleared CacheEntry / unsuccessful Factory
                // with our Factory
                supplier = factory;
            } else {
                // retry with current supplier
                supplier = valuesMap.get(subKey);
            }
        }
    }
}
 
Example 16
Source File: WeakCache.java    From openjdk-jdk8u-backup with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Look-up the value through the cache. This always evaluates the
 * {@code subKeyFactory} function and optionally evaluates
 * {@code valueFactory} function if there is no entry in the cache for given
 * pair of (key, subKey) or the entry has already been cleared.
 *
 * @param key       possibly null key
 * @param parameter parameter used together with key to create sub-key and
 *                  value (should not be null)
 * @return the cached value (never null)
 * @throws NullPointerException if {@code parameter} passed in or
 *                              {@code sub-key} calculated by
 *                              {@code subKeyFactory} or {@code value}
 *                              calculated by {@code valueFactory} is null.
 */
public V get(K key, P parameter) {
    Objects.requireNonNull(parameter);

    expungeStaleEntries();

    Object cacheKey = CacheKey.valueOf(key, refQueue);

    // lazily install the 2nd level valuesMap for the particular cacheKey
    ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);
    if (valuesMap == null) {
        ConcurrentMap<Object, Supplier<V>> oldValuesMap
            = map.putIfAbsent(cacheKey,
                              valuesMap = new ConcurrentHashMap<>());
        if (oldValuesMap != null) {
            valuesMap = oldValuesMap;
        }
    }

    // create subKey and retrieve the possible Supplier<V> stored by that
    // subKey from valuesMap
    Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
    Supplier<V> supplier = valuesMap.get(subKey);
    Factory factory = null;

    while (true) {
        if (supplier != null) {
            // supplier might be a Factory or a CacheValue<V> instance
            V value = supplier.get();
            if (value != null) {
                return value;
            }
        }
        // else no supplier in cache
        // or a supplier that returned null (could be a cleared CacheValue
        // or a Factory that wasn't successful in installing the CacheValue)

        // lazily construct a Factory
        if (factory == null) {
            factory = new Factory(key, parameter, subKey, valuesMap);
        }

        if (supplier == null) {
            supplier = valuesMap.putIfAbsent(subKey, factory);
            if (supplier == null) {
                // successfully installed Factory
                supplier = factory;
            }
            // else retry with winning supplier
        } else {
            if (valuesMap.replace(subKey, supplier, factory)) {
                // successfully replaced
                // cleared CacheEntry / unsuccessful Factory
                // with our Factory
                supplier = factory;
            } else {
                // retry with current supplier
                supplier = valuesMap.get(subKey);
            }
        }
    }
}
 
Example 17
Source File: WeakCache.java    From openjdk-jdk8u with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Look-up the value through the cache. This always evaluates the
 * {@code subKeyFactory} function and optionally evaluates
 * {@code valueFactory} function if there is no entry in the cache for given
 * pair of (key, subKey) or the entry has already been cleared.
 *
 * @param key       possibly null key
 * @param parameter parameter used together with key to create sub-key and
 *                  value (should not be null)
 * @return the cached value (never null)
 * @throws NullPointerException if {@code parameter} passed in or
 *                              {@code sub-key} calculated by
 *                              {@code subKeyFactory} or {@code value}
 *                              calculated by {@code valueFactory} is null.
 */
public V get(K key, P parameter) {
    Objects.requireNonNull(parameter);

    expungeStaleEntries();

    Object cacheKey = CacheKey.valueOf(key, refQueue);

    // lazily install the 2nd level valuesMap for the particular cacheKey
    ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);
    if (valuesMap == null) {
        ConcurrentMap<Object, Supplier<V>> oldValuesMap
            = map.putIfAbsent(cacheKey,
                              valuesMap = new ConcurrentHashMap<>());
        if (oldValuesMap != null) {
            valuesMap = oldValuesMap;
        }
    }

    // create subKey and retrieve the possible Supplier<V> stored by that
    // subKey from valuesMap
    Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
    Supplier<V> supplier = valuesMap.get(subKey);
    Factory factory = null;

    while (true) {
        if (supplier != null) {
            // supplier might be a Factory or a CacheValue<V> instance
            V value = supplier.get();
            if (value != null) {
                return value;
            }
        }
        // else no supplier in cache
        // or a supplier that returned null (could be a cleared CacheValue
        // or a Factory that wasn't successful in installing the CacheValue)

        // lazily construct a Factory
        if (factory == null) {
            factory = new Factory(key, parameter, subKey, valuesMap);
        }

        if (supplier == null) {
            supplier = valuesMap.putIfAbsent(subKey, factory);
            if (supplier == null) {
                // successfully installed Factory
                supplier = factory;
            }
            // else retry with winning supplier
        } else {
            if (valuesMap.replace(subKey, supplier, factory)) {
                // successfully replaced
                // cleared CacheEntry / unsuccessful Factory
                // with our Factory
                supplier = factory;
            } else {
                // retry with current supplier
                supplier = valuesMap.get(subKey);
            }
        }
    }
}
 
Example 18
Source File: ConcurrentMapTest.java    From concurrentlinkedhashmap with Apache License 2.0 4 votes vote down vote up
@Test(dataProvider = "guardedMap", expectedExceptions = NullPointerException.class)
public void replaceConditionally_withNullOldValue(ConcurrentMap<Integer, Integer> map) {
  map.replace(1, null, 3);
}
 
Example 19
Source File: WeakCache.java    From dragonwell8_jdk with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Look-up the value through the cache. This always evaluates the
 * {@code subKeyFactory} function and optionally evaluates
 * {@code valueFactory} function if there is no entry in the cache for given
 * pair of (key, subKey) or the entry has already been cleared.
 *
 * @param key       possibly null key
 * @param parameter parameter used together with key to create sub-key and
 *                  value (should not be null)
 * @return the cached value (never null)
 * @throws NullPointerException if {@code parameter} passed in or
 *                              {@code sub-key} calculated by
 *                              {@code subKeyFactory} or {@code value}
 *                              calculated by {@code valueFactory} is null.
 */
public V get(K key, P parameter) {
    Objects.requireNonNull(parameter);

    expungeStaleEntries();

    Object cacheKey = CacheKey.valueOf(key, refQueue);

    // lazily install the 2nd level valuesMap for the particular cacheKey
    ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);
    if (valuesMap == null) {
        ConcurrentMap<Object, Supplier<V>> oldValuesMap
            = map.putIfAbsent(cacheKey,
                              valuesMap = new ConcurrentHashMap<>());
        if (oldValuesMap != null) {
            valuesMap = oldValuesMap;
        }
    }

    // create subKey and retrieve the possible Supplier<V> stored by that
    // subKey from valuesMap
    Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
    Supplier<V> supplier = valuesMap.get(subKey);
    Factory factory = null;

    while (true) {
        if (supplier != null) {
            // supplier might be a Factory or a CacheValue<V> instance
            V value = supplier.get();
            if (value != null) {
                return value;
            }
        }
        // else no supplier in cache
        // or a supplier that returned null (could be a cleared CacheValue
        // or a Factory that wasn't successful in installing the CacheValue)

        // lazily construct a Factory
        if (factory == null) {
            factory = new Factory(key, parameter, subKey, valuesMap);
        }

        if (supplier == null) {
            supplier = valuesMap.putIfAbsent(subKey, factory);
            if (supplier == null) {
                // successfully installed Factory
                supplier = factory;
            }
            // else retry with winning supplier
        } else {
            if (valuesMap.replace(subKey, supplier, factory)) {
                // successfully replaced
                // cleared CacheEntry / unsuccessful Factory
                // with our Factory
                supplier = factory;
            } else {
                // retry with current supplier
                supplier = valuesMap.get(subKey);
            }
        }
    }
}
 
Example 20
Source File: ConcurrentMapTest.java    From concurrentlinkedhashmap with Apache License 2.0 4 votes vote down vote up
@Test(dataProvider = "guardedMap", expectedExceptions = NullPointerException.class)
public void replace_withNullValue(ConcurrentMap<Integer, Integer> map) {
  map.replace(1, null);
}