Java Code Examples for java.util.concurrent.atomic.AtomicReferenceArray#set()

The following examples show how to use java.util.concurrent.atomic.AtomicReferenceArray#set() . 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: AtomicReferenceArrayTest.java    From j2objc with Apache License 2.0 5 votes vote down vote up
/**
 * repeated weakCompareAndSet succeeds in changing value when equal
 * to expected
 */
public void testWeakCompareAndSet() {
    AtomicReferenceArray aa = new AtomicReferenceArray(SIZE);
    for (int i = 0; i < SIZE; i++) {
        aa.set(i, one);
        do {} while (!aa.weakCompareAndSet(i, one, two));
        do {} while (!aa.weakCompareAndSet(i, two, m4));
        assertSame(m4, aa.get(i));
        do {} while (!aa.weakCompareAndSet(i, m4, seven));
        assertSame(seven, aa.get(i));
    }
}
 
Example 2
Source File: AtomicReferenceArrayTest.java    From openjdk-jdk9 with GNU General Public License v2.0 5 votes vote down vote up
/**
 * a deserialized serialized array holds same values
 */
public void testSerialization() throws Exception {
    AtomicReferenceArray x = new AtomicReferenceArray(SIZE);
    for (int i = 0; i < SIZE; i++) {
        x.set(i, new Integer(-i));
    }
    AtomicReferenceArray y = serialClone(x);
    assertNotSame(x, y);
    assertEquals(x.length(), y.length());
    for (int i = 0; i < SIZE; i++) {
        assertEquals(x.get(i), y.get(i));
    }
}
 
Example 3
Source File: AtomicReferenceArrayTest.java    From openjdk-jdk9 with GNU General Public License v2.0 5 votes vote down vote up
/**
 * getAndSet returns previous value and sets to given value at given index
 */
public void testGetAndSet() {
    AtomicReferenceArray aa = new AtomicReferenceArray(SIZE);
    for (int i = 0; i < SIZE; i++) {
        aa.set(i, one);
        assertSame(one, aa.getAndSet(i, zero));
        assertSame(zero, aa.getAndSet(i, m10));
        assertSame(m10, aa.getAndSet(i, one));
    }
}
 
Example 4
Source File: LocalCache.java    From codebuff with BSD 2-Clause "Simplified" License 5 votes vote down vote up
void clear() {
  if (count != 0) { // read-volatile
    lock();
    try {
      long now = map.ticker.read();
      preWriteCleanup(now);
      AtomicReferenceArray<ReferenceEntry<K, V>> table = this.table;
      for (int i = 0; i < table.length(); ++i) {
        for (ReferenceEntry<K, V> e = table.get(i); e != null; e = e.getNext()) {
          // Loading references aren't actually in the map yet.
          if (e.getValueReference().isActive()) {
            K key = e.getKey();
            V value = e.getValueReference().get();
            RemovalCause cause = (key == null || value == null) ? RemovalCause.COLLECTED : RemovalCause.EXPLICIT;
            enqueueNotification(key, e.getHash(), value, e.getValueReference().getWeight(), cause);
          }
        }
      }
      for (int i = 0; i < table.length(); ++i) {
        table.set(i, null);
      }
      clearReferenceQueues();
      writeQueue.clear();
      accessQueue.clear();
      readCount.set(0);
      ++modCount;
      count = 0; // write-volatile
    } finally {
      unlock();
      postWriteCleanup();
    }
  }
}
 
Example 5
Source File: AtomicReferenceArray9Test.java    From openjdk-jdk9 with GNU General Public License v2.0 5 votes vote down vote up
/**
 * compareAndExchange succeeds in changing value if equal to
 * expected else fails
 */
public void testCompareAndExchange() {
    AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<>(SIZE);
    for (int i = 0; i < SIZE; i++) {
        aa.set(i, one);
        assertEquals(one, aa.compareAndExchange(i, one, two));
        assertEquals(two, aa.compareAndExchange(i, two, m4));
        assertEquals(m4, aa.get(i));
        assertEquals(m4, aa.compareAndExchange(i,m5, seven));
        assertEquals(m4, aa.get(i));
        assertEquals(m4, aa.compareAndExchange(i, m4, seven));
        assertEquals(seven, aa.get(i));
    }
}
 
Example 6
Source File: MapMakerInternalMap.java    From codebuff with BSD 2-Clause "Simplified" License 5 votes vote down vote up
boolean remove(Object key, int hash, Object value) {
  lock();
  try {
    preWriteCleanup();
    int newCount = this.count - 1;
    AtomicReferenceArray<ReferenceEntry<K, V>> table = this.table;
    int index = hash & (table.length() - 1);
    ReferenceEntry<K, V> first = table.get(index);
    for (ReferenceEntry<K, V> e = first; e != null; e = e.getNext()) {
      K entryKey = e.getKey();
      if (e.getHash() == hash && entryKey != null
          && map.keyEquivalence.equivalent(key, entryKey)) {
        ValueReference<K, V> valueReference = e.getValueReference();
        V entryValue = valueReference.get();
        boolean explicitRemoval = false;
        if (map.valueEquivalence.equivalent(value, entryValue)) {
          explicitRemoval = true;
        } else if (isCollected(valueReference)) {
          // TODO(kak): Remove this branch
        } else {
          return false;
        }

        ++modCount;
        ReferenceEntry<K, V> newFirst = removeFromChain(first, e);
        newCount = this.count - 1;
        table.set(index, newFirst);
        this.count = newCount; // write-volatile
        return explicitRemoval;
      }
    }
    return false;
  } finally {
    unlock();
  }
}
 
Example 7
Source File: AtomicReferenceArrayTest.java    From j2objc with Apache License 2.0 5 votes vote down vote up
/**
 * getAndSet returns previous value and sets to given value at given index
 */
public void testGetAndSet() {
    AtomicReferenceArray aa = new AtomicReferenceArray(SIZE);
    for (int i = 0; i < SIZE; i++) {
        aa.set(i, one);
        assertSame(one, aa.getAndSet(i, zero));
        assertSame(zero, aa.getAndSet(i, m10));
        assertSame(m10, aa.getAndSet(i, one));
    }
}
 
Example 8
Source File: AtomicReferenceArrayTest.java    From openjdk-jdk9 with GNU General Public License v2.0 5 votes vote down vote up
/**
 * repeated weakCompareAndSet succeeds in changing value when equal
 * to expected
 */
public void testWeakCompareAndSet() {
    AtomicReferenceArray aa = new AtomicReferenceArray(SIZE);
    for (int i = 0; i < SIZE; i++) {
        aa.set(i, one);
        do {} while (!aa.weakCompareAndSet(i, one, two));
        do {} while (!aa.weakCompareAndSet(i, two, m4));
        assertSame(m4, aa.get(i));
        do {} while (!aa.weakCompareAndSet(i, m4, seven));
        assertSame(seven, aa.get(i));
    }
}
 
Example 9
Source File: MapMakerInternalMap.java    From codebuff with BSD 2-Clause "Simplified" License 5 votes vote down vote up
/**
 * Removes an entry whose value has been garbage collected.
 */

@CanIgnoreReturnValue
boolean reclaimValue(K key, int hash, ValueReference<K, V> valueReference) {
  lock();
  try {
    int newCount = this.count - 1;
    AtomicReferenceArray<ReferenceEntry<K, V>> table = this.table;
    int index = hash & (table.length() - 1);
    ReferenceEntry<K, V> first = table.get(index);
    for (ReferenceEntry<K, V> e = first; e != null; e = e.getNext()) {
      K entryKey = e.getKey();
      if (e.getHash() == hash && entryKey != null
          && map.keyEquivalence.equivalent(key, entryKey)) {
        ValueReference<K, V> v = e.getValueReference();
        if (v == valueReference) {
          ++modCount;
          ReferenceEntry<K, V> newFirst = removeFromChain(first, e);
          newCount = this.count - 1;
          table.set(index, newFirst);
          this.count = newCount; // write-volatile
          return true;
        }
        return false;
      }
    }
    return false;
  } finally {
    unlock();
  }
}
 
Example 10
Source File: MapMakerInternalMap.java    From codebuff with BSD 2-Clause "Simplified" License 5 votes vote down vote up
/**
 * Removes an entry whose value has been garbage collected.
 */
@CanIgnoreReturnValue
boolean reclaimValue(K key, int hash, ValueReference<K, V> valueReference) {
  lock();
  try {
    int newCount = this.count - 1;
    AtomicReferenceArray<ReferenceEntry<K, V>> table = this.table;
    int index = hash & (table.length() - 1);
    ReferenceEntry<K, V> first = table.get(index);

    for (ReferenceEntry<K, V> e = first; e != null; e = e.getNext()) {
      K entryKey = e.getKey();
      if (e.getHash() == hash
          && entryKey != null
          && map.keyEquivalence.equivalent(key, entryKey)) {
        ValueReference<K, V> v = e.getValueReference();
        if (v == valueReference) {
          ++modCount;
          ReferenceEntry<K, V> newFirst = removeFromChain(first, e);
          newCount = this.count - 1;
          table.set(index, newFirst);
          this.count = newCount; // write-volatile
          return true;
        }
        return false;
      }
    }

    return false;
  } finally {
    unlock();
  }
}
 
Example 11
Source File: LocalCache.java    From codebuff with BSD 2-Clause "Simplified" License 4 votes vote down vote up
boolean storeLoadedValue(K key, int hash, LoadingValueReference<K, V> oldValueReference, V newValue) {
  lock();
  try {
    long now = map.ticker.read();
    preWriteCleanup(now);
    int newCount = this.count + 1;
    if (newCount > this.threshold) { // ensure capacity
      expand();
      newCount = this.count + 1;
    }
    AtomicReferenceArray<ReferenceEntry<K, V>> table = this.table;
    int index = hash & (table.length() - 1);
    ReferenceEntry<K, V> first = table.get(index);
    for (ReferenceEntry<K, V> e = first; e != null; e = e.getNext()) {
      K entryKey = e.getKey();
      if (e.getHash() == hash && entryKey != null
          && map.keyEquivalence.equivalent(key, entryKey)) {
        ValueReference<K, V> valueReference = e.getValueReference();
        V entryValue = valueReference.get();
        // replace the old LoadingValueReference if it's live, otherwise
        // perform a putIfAbsent
        if (oldValueReference == valueReference
            || (entryValue == null && valueReference != UNSET)) {
          ++modCount;
          if (oldValueReference.isActive()) {
            RemovalCause cause = (entryValue == null) ? RemovalCause.COLLECTED : RemovalCause.REPLACED;
            enqueueNotification(key, hash, entryValue, oldValueReference.getWeight(), cause);
            newCount--;
          }
          setValue(e, key, newValue, now);
          this.count = newCount; // write-volatile
          evictEntries(e);
          return true;
        }

        // the loaded value was already clobbered
        enqueueNotification(key, hash, newValue, 0, RemovalCause.REPLACED);
        return false;
      }
    }

    ++modCount;
    ReferenceEntry<K, V> newEntry = newEntry(key, hash, first);
    setValue(newEntry, key, newValue, now);
    table.set(index, newEntry);
    this.count = newCount; // write-volatile
    evictEntries(newEntry);
    return true;
  } finally {
    unlock();
    postWriteCleanup();
  }
}
 
Example 12
Source File: ResolveCache.java    From consulo with Apache License 2.0 4 votes vote down vote up
private static void clearArray(AtomicReferenceArray<?> array) {
  for (int i = 0; i < array.length(); i++) {
    array.set(i, null);
  }
}
 
Example 13
Source File: LocalCache.java    From codebuff with BSD 2-Clause "Simplified" License 4 votes vote down vote up
@Nullable
V put(K key, int hash, V value, boolean onlyIfAbsent) {
  lock();
  try {
    long now = map.ticker.read();
    preWriteCleanup(now);
    int newCount = this.count + 1;
    if (newCount > this.threshold) { // ensure capacity
      expand();
      newCount = this.count + 1;
    }
    AtomicReferenceArray<ReferenceEntry<K, V>> table = this.table;
    int index = hash & (table.length() - 1);
    ReferenceEntry<K, V> first = table.get(index);

    // Look for an existing entry.
    for (ReferenceEntry<K, V> e = first; e != null; e = e.getNext()) {
      K entryKey = e.getKey();
      if (e.getHash() == hash && entryKey != null
          && map.keyEquivalence.equivalent(key, entryKey)) {
        // We found an existing entry.
        ValueReference<K, V> valueReference = e.getValueReference();
        V entryValue = valueReference.get();
        if (entryValue == null) {
          ++modCount;
          if (valueReference.isActive()) {
            enqueueNotification(key, hash, entryValue, valueReference.getWeight(), RemovalCause.COLLECTED);
            setValue(e, key, value, now);
            newCount = this.count; // count remains unchanged
          } else {
            setValue(e, key, value, now);
            newCount = this.count + 1;
          }
          this.count = newCount; // write-volatile
          evictEntries(e);
          return null;
        }
        else if (onlyIfAbsent) {
          // Mimic
          // "if (!map.containsKey(key)) ...
          // else return map.get(key);
          recordLockedRead(e, now);
          return entryValue;
        } else {
          // clobber existing entry, count remains unchanged
          ++modCount;
          enqueueNotification(key, hash, entryValue, valueReference.getWeight(), RemovalCause.REPLACED);
          setValue(e, key, value, now);
          evictEntries(e);
          return entryValue;
        }
      }
    }

    // Create a new entry.

    ++modCount;
    ReferenceEntry<K, V> newEntry = newEntry(key, hash, first);
    setValue(newEntry, key, value, now);
    table.set(index, newEntry);
    newCount = this.count + 1;
    this.count = newCount; // write-volatile
    evictEntries(newEntry);
    return null;
  } finally {
    unlock();
    postWriteCleanup();
  }
}
 
Example 14
Source File: LocalCache.java    From codebuff with BSD 2-Clause "Simplified" License 4 votes vote down vote up
@Nullable
V put(K key, int hash, V value, boolean onlyIfAbsent) {
  lock();
  try {
    long now = map.ticker.read();
    preWriteCleanup(now);
    int newCount = this.count + 1;
    if (newCount > this.threshold) { // ensure capacity
      expand();
      newCount = this.count + 1;
    }
    AtomicReferenceArray<ReferenceEntry<K, V>> table = this.table;
    int index = hash & (table.length() - 1);
    ReferenceEntry<K, V> first = table.get(index);

    // Look for an existing entry.
    for (ReferenceEntry<K, V> e = first; e != null; e = e.getNext()) {
      K entryKey = e.getKey();
      if (e.getHash() == hash && entryKey != null
          && map.keyEquivalence.equivalent(key, entryKey)) {
        // We found an existing entry.
        ValueReference<K, V> valueReference = e.getValueReference();
        V entryValue = valueReference.get();
        if (entryValue == null) {
          ++modCount;
          if (valueReference.isActive()) {
            enqueueNotification(key, hash, entryValue, valueReference.getWeight(), RemovalCause.COLLECTED);
            setValue(e, key, value, now);
            newCount = this.count; // count remains unchanged
          } else {
            setValue(e, key, value, now);
            newCount = this.count + 1;
          }
          this.count = newCount; // write-volatile
          evictEntries(e);
          return null;
        }
        else if (onlyIfAbsent) {
          // Mimic
          // "if (!map.containsKey(key)) ...
          // else return map.get(key);
          recordLockedRead(e, now);
          return entryValue;
        } else {
          // clobber existing entry, count remains unchanged
          ++modCount;
          enqueueNotification(key, hash, entryValue, valueReference.getWeight(), RemovalCause.REPLACED);
          setValue(e, key, value, now);
          evictEntries(e);
          return entryValue;
        }
      }
    }

    // Create a new entry.

    ++modCount;
    ReferenceEntry<K, V> newEntry = newEntry(key, hash, first);
    setValue(newEntry, key, value, now);
    table.set(index, newEntry);
    newCount = this.count + 1;
    this.count = newCount; // write-volatile
    evictEntries(newEntry);
    return null;
  } finally {
    unlock();
    postWriteCleanup();
  }
}
 
Example 15
Source File: LocalCache.java    From codebuff with BSD 2-Clause "Simplified" License 4 votes vote down vote up
boolean storeLoadedValue(K key, int hash, LoadingValueReference<K, V> oldValueReference, V newValue) {
  lock();
  try {
    long now = map.ticker.read();
    preWriteCleanup(now);
    int newCount = this.count + 1;
    if (newCount > this.threshold) { // ensure capacity
      expand();
      newCount = this.count + 1;
    }
    AtomicReferenceArray<ReferenceEntry<K, V>> table = this.table;
    int index = hash & (table.length() - 1);
    ReferenceEntry<K, V> first = table.get(index);
    for (ReferenceEntry<K, V> e = first; e != null; e = e.getNext()) {
      K entryKey = e.getKey();
      if (e.getHash() == hash && entryKey != null
          && map.keyEquivalence.equivalent(key, entryKey)) {
        ValueReference<K, V> valueReference = e.getValueReference();
        V entryValue = valueReference.get();
        // replace the old LoadingValueReference if it's live, otherwise
        // perform a putIfAbsent
        if (oldValueReference == valueReference
            || (entryValue == null && valueReference != UNSET)) {
          ++modCount;
          if (oldValueReference.isActive()) {
            RemovalCause cause = (entryValue == null) ? RemovalCause.COLLECTED : RemovalCause.REPLACED;
            enqueueNotification(key, hash, entryValue, oldValueReference.getWeight(), cause);
            newCount--;
          }
          setValue(e, key, newValue, now);
          this.count = newCount; // write-volatile
          evictEntries(e);
          return true;
        }

        // the loaded value was already clobbered
        enqueueNotification(key, hash, newValue, 0, RemovalCause.REPLACED);
        return false;
      }
    }

    ++modCount;
    ReferenceEntry<K, V> newEntry = newEntry(key, hash, first);
    setValue(newEntry, key, newValue, now);
    table.set(index, newEntry);
    this.count = newCount; // write-volatile
    evictEntries(newEntry);
    return true;
  } finally {
    unlock();
    postWriteCleanup();
  }
}
 
Example 16
Source File: LocalCache.java    From codebuff with BSD 2-Clause "Simplified" License 4 votes vote down vote up
boolean replace(K key, int hash, V oldValue, V newValue) {
  lock();
  try {
    long now = map.ticker.read();
    preWriteCleanup(now);
    AtomicReferenceArray<ReferenceEntry<K, V>> table = this.table;
    int index = hash & (table.length() - 1);
    ReferenceEntry<K, V> first = table.get(index);
    for (ReferenceEntry<K, V> e = first; e != null; e = e.getNext()) {
      K entryKey = e.getKey();
      if (e.getHash() == hash && entryKey != null
          && map.keyEquivalence.equivalent(key, entryKey)) {
        ValueReference<K, V> valueReference = e.getValueReference();
        V entryValue = valueReference.get();
        if (entryValue == null) {
          if (valueReference.isActive()) {
            // If the value disappeared, this entry is partially collected.
            int newCount = this.count - 1;
            ++modCount;
            ReferenceEntry<K, V> newFirst = removeValueFromChain(first, e, entryKey, hash, entryValue, valueReference, RemovalCause.COLLECTED);
            newCount = this.count - 1;
            table.set(index, newFirst);
            this.count = newCount; // write-volatile
          }
          return false;
        }
        if (map.valueEquivalence.equivalent(oldValue, entryValue)) {
          ++modCount;
          enqueueNotification(key, hash, entryValue, valueReference.getWeight(), RemovalCause.REPLACED);
          setValue(e, key, newValue, now);
          evictEntries(e);
          return true;
        } else {
          // Mimic
          // "if (map.containsKey(key) && map.get(key).equals(oldValue))..."
          recordLockedRead(e, now);
          return false;
        }
      }
    }
    return false;
  } finally {
    unlock();
    postWriteCleanup();
  }
}
 
Example 17
Source File: LocalCache.java    From codebuff with BSD 2-Clause "Simplified" License 4 votes vote down vote up
boolean replace(K key, int hash, V oldValue, V newValue) {
  lock();
  try {
    long now = map.ticker.read();
    preWriteCleanup(now);
    AtomicReferenceArray<ReferenceEntry<K, V>> table = this.table;
    int index = hash & (table.length() - 1);
    ReferenceEntry<K, V> first = table.get(index);
    for (ReferenceEntry<K, V> e = first; e != null; e = e.getNext()) {
      K entryKey = e.getKey();
      if (e.getHash() == hash && entryKey != null
          && map.keyEquivalence.equivalent(key, entryKey)) {
        ValueReference<K, V> valueReference = e.getValueReference();
        V entryValue = valueReference.get();
        if (entryValue == null) {
          if (valueReference.isActive()) {
            // If the value disappeared, this entry is partially collected.
            int newCount = this.count - 1;
            ++modCount;
            ReferenceEntry<K, V> newFirst = removeValueFromChain(first, e, entryKey, hash, entryValue, valueReference, RemovalCause.COLLECTED);
            newCount = this.count - 1;
            table.set(index, newFirst);
            this.count = newCount; // write-volatile
          }
          return false;
        }
        if (map.valueEquivalence.equivalent(oldValue, entryValue)) {
          ++modCount;
          enqueueNotification(key, hash, entryValue, valueReference.getWeight(), RemovalCause.REPLACED);
          setValue(e, key, newValue, now);
          evictEntries(e);
          return true;
        } else {
          // Mimic
          // "if (map.containsKey(key) && map.get(key).equals(oldValue))..."
          recordLockedRead(e, now);
          return false;
        }
      }
    }
    return false;
  } finally {
    unlock();
    postWriteCleanup();
  }
}
 
Example 18
Source File: LocalCache.java    From bazel-buildfarm with Apache License 2.0 4 votes vote down vote up
boolean replace(K key, int hash, V oldValue, V newValue) {
  lock();
  try {
    long now = map.ticker.read();
    preWriteCleanup(now);

    AtomicReferenceArray<ReferenceEntry<K, V>> table = this.table;
    int index = hash & (table.length() - 1);
    ReferenceEntry<K, V> first = table.get(index);

    for (ReferenceEntry<K, V> e = first; e != null; e = e.getNext()) {
      K entryKey = e.getKey();
      if (e.getHash() == hash
          && entryKey != null
          && map.keyEquivalence.equivalent(key, entryKey)) {
        ValueReference<K, V> valueReference = e.getValueReference();
        V entryValue = valueReference.get();
        if (entryValue == null) {
          if (valueReference.isActive()) {
            // If the value disappeared, this entry is partially collected.
            int newCount = this.count - 1;
            ++modCount;
            ReferenceEntry<K, V> newFirst =
                removeValueFromChain(
                    first,
                    e,
                    entryKey,
                    hash,
                    entryValue,
                    valueReference,
                    RemovalCause.COLLECTED);
            newCount = this.count - 1;
            table.set(index, newFirst);
            this.count = newCount; // write-volatile
          }
          return false;
        }

        if (map.valueEquivalence.equivalent(oldValue, entryValue)) {
          ++modCount;
          enqueueNotification(
              key, hash, entryValue, valueReference.getWeight(), RemovalCause.REPLACED);
          setValue(e, key, newValue, now);
          evictEntries(e);
          return true;
        } else {
          // Mimic
          // "if (map.containsKey(key) && map.get(key).equals(oldValue))..."
          recordLockedRead(e, now);
          return false;
        }
      }
    }

    return false;
  } finally {
    unlock();
    postWriteCleanup();
  }
}
 
Example 19
Source File: LocalCache.java    From bazel-buildfarm with Apache License 2.0 4 votes vote down vote up
boolean storeLoadedValue(
    K key, int hash, LoadingValueReference<K, V> oldValueReference, V newValue) {
  lock();
  try {
    long now = map.ticker.read();
    preWriteCleanup(now);

    int newCount = this.count + 1;
    if (newCount > this.threshold) { // ensure capacity
      expand();
      newCount = this.count + 1;
    }

    AtomicReferenceArray<ReferenceEntry<K, V>> table = this.table;
    int index = hash & (table.length() - 1);
    ReferenceEntry<K, V> first = table.get(index);

    for (ReferenceEntry<K, V> e = first; e != null; e = e.getNext()) {
      K entryKey = e.getKey();
      if (e.getHash() == hash
          && entryKey != null
          && map.keyEquivalence.equivalent(key, entryKey)) {
        ValueReference<K, V> valueReference = e.getValueReference();
        V entryValue = valueReference.get();
        // replace the old LoadingValueReference if it's live, otherwise
        // perform a putIfAbsent
        if (oldValueReference == valueReference
            || (entryValue == null && valueReference != UNSET)) {
          ++modCount;
          if (oldValueReference.isActive()) {
            RemovalCause cause =
                (entryValue == null) ? RemovalCause.COLLECTED : RemovalCause.REPLACED;
            enqueueNotification(key, hash, entryValue, oldValueReference.getWeight(), cause);
            newCount--;
          }
          setValue(e, key, newValue, now);
          this.count = newCount; // write-volatile
          evictEntries(e);
          return true;
        }

        // the loaded value was already clobbered
        enqueueNotification(key, hash, newValue, 0, RemovalCause.REPLACED);
        return false;
      }
    }

    ++modCount;
    ReferenceEntry<K, V> newEntry = newEntry(key, hash, first);
    setValue(newEntry, key, newValue, now);
    table.set(index, newEntry);
    this.count = newCount; // write-volatile
    evictEntries(newEntry);
    return true;
  } finally {
    unlock();
    postWriteCleanup();
  }
}
 
Example 20
Source File: LocalCache.java    From codebuff with BSD 2-Clause "Simplified" License 4 votes vote down vote up
V lockedGetOrLoad(K key, int hash, CacheLoader<? super K, V> loader) throws ExecutionException {
  ReferenceEntry<K, V> e;
  ValueReference<K, V> valueReference = null;
  LoadingValueReference<K, V> loadingValueReference = null;
  boolean createNewEntry = true;
  lock();
  try {
    // re-read ticker once inside the lock
    long now = map.ticker.read();
    preWriteCleanup(now);
    int newCount = this.count - 1;
    AtomicReferenceArray<ReferenceEntry<K, V>> table = this.table;
    int index = hash & (table.length() - 1);
    ReferenceEntry<K, V> first = table.get(index);
    for (e = first; e != null; e = e.getNext()) {
      K entryKey = e.getKey();
      if (e.getHash() == hash && entryKey != null
          && map.keyEquivalence.equivalent(key, entryKey)) {
        valueReference = e.getValueReference();
        if (valueReference.isLoading()) {
          createNewEntry = false;
        } else {
          V value = valueReference.get();
          if (value == null) {
            enqueueNotification(entryKey, hash, value, valueReference.getWeight(), RemovalCause.COLLECTED);
          } else if (map.isExpired(e, now)) {
            // This is a duplicate check, as preWriteCleanup already purged expired
            // entries, but let's accomodate an incorrect expiration queue.
            enqueueNotification(entryKey, hash, value, valueReference.getWeight(), RemovalCause.EXPIRED);
          } else {
            recordLockedRead(e, now);
            statsCounter.recordHits(1);
            // we were concurrent with loading; don't consider refresh
            return value;
          }

          // immediately reuse invalid entries
          writeQueue.remove(e);
          accessQueue.remove(e);
          this.count = newCount; // write-volatile
        }
        break;
      }
    }
    if (createNewEntry) {
      loadingValueReference = new LoadingValueReference<K, V>();
      if (e == null) {
        e = newEntry(key, hash, first);
        e.setValueReference(loadingValueReference);
        table.set(index, e);
      } else {
        e.setValueReference(loadingValueReference);
      }
    }
  } finally {
    unlock();
    postWriteCleanup();
  }
  if (createNewEntry) {
    try {
      // Synchronizes on the entry to allow failing fast when a recursive load is
      // detected. This may be circumvented when an entry is copied, but will fail fast most
      // of the time.
      synchronized (e) {
        return loadSync(key, hash, loadingValueReference, loader);
      }
    } finally {
      statsCounter.recordMisses(1);
    }
  } else {
    // The entry already exists. Wait for loading.
    return waitForLoadingValue(e, key, valueReference);
  }
}