public boolean offer(E e) { if (e == null) { throw new NullPointerException("Null is not a valid element"); } AtomicReferenceArray<E> buffer = this.buffer; int mask = this.mask; long index = this.producerIndex.get(); int offset = calcElementOffset(index, mask); if (index >= this.producerLookAhead) { int step = this.lookAheadStep; if (lvElement(buffer, calcElementOffset(((long) step) + index, mask)) == null) { this.producerLookAhead = ((long) step) + index; } else if (lvElement(buffer, offset) != null) { return false; } } soProducerIndex(1 + index); soElement(buffer, offset, e); return true; }
@GuardedBy("Segment.this") boolean removeEntry(ReferenceEntry<K, V> entry, int hash, RemovalCause cause) { 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()) { if (e == entry) { ++modCount; enqueueNotification(e.getKey(), hash, e.getValueReference().get(), cause); ReferenceEntry<K, V> newFirst = removeFromChain(first, e); newCount = this.count - 1; table.set(index, newFirst); this.count = newCount; // write-volatile return true; } } return false; }
@Override protected NodesGatewayMetaState newResponse(Request request, AtomicReferenceArray responses) { final List<NodeGatewayMetaState> nodesList = new ArrayList<>(); final List<FailedNodeException> failures = new ArrayList<>(); for (int i = 0; i < responses.length(); i++) { Object resp = responses.get(i); if (resp instanceof NodeGatewayMetaState) { // will also filter out null response for unallocated ones nodesList.add((NodeGatewayMetaState) resp); } else if (resp instanceof FailedNodeException) { failures.add((FailedNodeException) resp); } else { logger.warn("unknown response type [{}], expected NodeLocalGatewayMetaState or FailedNodeException", resp); } } return new NodesGatewayMetaState(clusterName, nodesList.toArray(new NodeGatewayMetaState[nodesList.size()]), failures.toArray(new FailedNodeException[failures.size()])); }
public void start() { if (shardsIts.size() == 0) { // no shards try { listener.onResponse(newResponse(request, new AtomicReferenceArray(0), clusterState)); } catch (Exception e) { listener.onFailure(e); } return; } // count the local operations, and perform the non local ones int shardIndex = -1; for (final ShardIterator shardIt : shardsIts) { shardIndex++; final ShardRouting shard = shardIt.nextOrNull(); if (shard != null) { performOperation(shardIt, shard, shardIndex); } else { // really, no shards active in this group onOperation(null, shardIt, shardIndex, new NoShardAvailableActionException(shardIt.shardId())); } } }
@SuppressWarnings("unchecked") protected TasksResponse newResponse(TasksRequest request, AtomicReferenceArray responses) { List<TaskResponse> tasks = new ArrayList<>(); List<FailedNodeException> failedNodeExceptions = new ArrayList<>(); List<TaskOperationFailure> taskOperationFailures = new ArrayList<>(); for (int i = 0; i < responses.length(); i++) { Object response = responses.get(i); if (response instanceof FailedNodeException) { failedNodeExceptions.add((FailedNodeException) response); } else { NodeTasksResponse tasksResponse = (NodeTasksResponse) response; if (tasksResponse.results != null) { tasks.addAll(tasksResponse.results); } if (tasksResponse.exceptions != null) { taskOperationFailures.addAll(tasksResponse.exceptions); } } } return newResponse(request, tasks, taskOperationFailures, failedNodeExceptions); }
private ArrayList arrayFrom(AtomicReferenceArray atomicArray) { // cache atomic array length in variable int len = atomicArray.length(); // create new arraylist ArrayList newList = new ArrayList<>(atomicArray.length()); // iterate over atomic array and copy to arraylist for (int i = 0; i < len; i++) { newList.add(atomicArray.get(i)); } // return new arraylist return newList; }
private ArrayList<TElement> arrayFrom(AtomicReferenceArray<TElement> atomicArray) { // cache atomic array length in variable int len = atomicArray.length(); // create new arraylist ArrayList<TElement> newList = new ArrayList<>(atomicArray.length()); // iterate over atomic array and copy to arraylist for (int i = 0; i < len; i++) { newList.add(atomicArray.get(i)); } // return new arraylist return newList; }
public final boolean offer(T e) { if (e == null) { throw new NullPointerException(); } AtomicReferenceArray<Object> buffer = this.producerBuffer; long index = lpProducerIndex(); int mask = this.producerMask; int offset = calcWrappedOffset(index, mask); if (index < this.producerLookAhead) { return writeToQueue(buffer, e, index, offset); } int lookAheadStep = this.producerLookAheadStep; if (lvElement(buffer, calcWrappedOffset(((long) lookAheadStep) + index, mask)) == null) { this.producerLookAhead = (((long) lookAheadStep) + index) - 1; return writeToQueue(buffer, e, index, offset); } else if (lvElement(buffer, calcWrappedOffset(1 + index, mask)) != null) { return writeToQueue(buffer, e, index, offset); } else { resize(buffer, index, offset, e, (long) mask); return true; } }
public void testSegmentRefresh_duplicate() throws ExecutionException { LocalCache<Object, Object> map = makeLocalCache(createCacheBuilder() .concurrencyLevel(1)); Segment<Object, Object> segment = map.segments[0]; Object key = new Object(); int hash = map.hash(key); AtomicReferenceArray<ReferenceEntry<Object, Object>> table = segment.table; int index = hash & (table.length() - 1); // already loading DummyEntry<Object, Object> entry = DummyEntry.create(key, hash, null); DummyValueReference<Object, Object> valueRef = DummyValueReference.create(null); valueRef.setLoading(true); entry.setValueReference(valueRef); table.set(index, entry); assertNull(segment.refresh(key, hash, identityLoader(), false)); }
@GuardedBy("this") boolean removeEntryForTesting(E entry) { int hash = entry.getHash(); int newCount = this.count - 1; AtomicReferenceArray<E> table = this.table; int index = hash & (table.length() - 1); E first = table.get(index); for (E e = first; e != null; e = e.getNext()) { if (e == entry) { ++modCount; E newFirst = removeFromChain(first, e); newCount = this.count - 1; table.set(index, newFirst); this.count = newCount; // write-volatile return true; } } return false; }
void clear() { if (count != 0) { lock(); try { AtomicReferenceArray<E> table = this.table; for (int i = 0; i < table.length(); ++i) { table.set(i, null); } maybeClearReferenceQueues(); readCount.set(0); ++modCount; count = 0; // write-volatile } finally { unlock(); } } }
/** * get and set for out of bound indices throw IndexOutOfBoundsException */ public void testIndexing() { AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<>(SIZE); for (int index : new int[] { -1, SIZE }) { final int j = index; final Runnable[] tasks = { () -> aa.getPlain(j), () -> aa.getOpaque(j), () -> aa.getAcquire(j), () -> aa.setPlain(j, null), () -> aa.setOpaque(j, null), () -> aa.setRelease(j, null), () -> aa.compareAndExchange(j, null, null), () -> aa.compareAndExchangeAcquire(j, null, null), () -> aa.compareAndExchangeRelease(j, null, null), () -> aa.weakCompareAndSetPlain(j, null, null), () -> aa.weakCompareAndSetVolatile(j, null, null), () -> aa.weakCompareAndSetAcquire(j, null, null), () -> aa.weakCompareAndSetRelease(j, null, null), }; assertThrows(IndexOutOfBoundsException.class, tasks); } }
@Override protected NodesGatewayStartedShards newResponse(Request request, AtomicReferenceArray responses) { final List<NodeGatewayStartedShards> nodesList = new ArrayList<>(); final List<FailedNodeException> failures = new ArrayList<>(); for (int i = 0; i < responses.length(); i++) { Object resp = responses.get(i); if (resp instanceof NodeGatewayStartedShards) { // will also filter out null response for unallocated ones nodesList.add((NodeGatewayStartedShards) resp); } else if (resp instanceof FailedNodeException) { failures.add((FailedNodeException) resp); } else { logger.warn("unknown response type [{}], expected NodeLocalGatewayStartedShards or FailedNodeException", resp); } } return new NodesGatewayStartedShards(clusterName, nodesList.toArray(new NodeGatewayStartedShards[nodesList.size()]), failures.toArray(new FailedNodeException[failures.size()])); }
/** Removes an entry whose key has been garbage collected. */ @CanIgnoreReturnValue boolean reclaimKey(E entry, int hash) { lock(); try { int newCount = count - 1; AtomicReferenceArray<E> table = this.table; int index = hash & (table.length() - 1); E first = table.get(index); for (E e = first; e != null; e = e.getNext()) { if (e == entry) { ++modCount; E newFirst = removeFromChain(first, e); newCount = this.count - 1; table.set(index, newFirst); this.count = newCount; // write-volatile return true; } } return false; } finally { unlock(); } }
public void testRemoveEntry() { MapMakerInternalMap<Object, Object, ?, ?> map = makeMap(createMapMaker().concurrencyLevel(1).initialCapacity(1)); Segment<Object, Object, ?, ?> segment = map.segments[0]; AtomicReferenceArray<? extends InternalEntry<Object, Object, ?>> table = segment.table; assertEquals(1, table.length()); Object key = new Object(); Object value = new Object(); int hash = map.hash(key); InternalEntry<Object, Object, ?> entry = segment.newEntryForTesting(key, hash, null); segment.setValueForTesting(entry, value); // remove absent assertFalse(segment.removeTableEntryForTesting(entry)); segment.setTableEntryForTesting(0, entry); segment.count = 1; assertTrue(segment.removeTableEntryForTesting(entry)); assertEquals(0, segment.count); assertNull(table.get(0)); }
/** * repeated weakCompareAndSetVolatile succeeds in changing value when equal * to expected */ public void testWeakCompareAndSetVolatile() { AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<>(SIZE); for (int i = 0; i < SIZE; i++) { aa.set(i, one); do {} while (!aa.weakCompareAndSetVolatile(i, one, two)); do {} while (!aa.weakCompareAndSetVolatile(i, two, m4)); assertEquals(m4, aa.get(i)); do {} while (!aa.weakCompareAndSetVolatile(i, m4, seven)); assertEquals(seven, aa.get(i)); } }
/** * get returns the last value setOpaque */ public void testGetSetOpaque() { AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<>(SIZE); for (int i = 0; i < SIZE; i++) { aa.setOpaque(i, one); assertEquals(one, aa.get(i)); aa.setOpaque(i, two); assertEquals(two, aa.get(i)); aa.setOpaque(i, m3); assertEquals(m3, aa.get(i)); } }
void initTable(AtomicReferenceArray<ReferenceEntry<K, V>> newTable) { this.threshold = newTable.length() * 3 / 4; // 0.75 if (this.threshold == maxSegmentSize) { // prevent spurious expansion before eviction this.threshold++; } this.table = newTable; }
void clear() { if (count != 0) { lock(); try { AtomicReferenceArray<ReferenceEntry<K, V>> table = this.table; if (map.removalNotificationQueue != DISCARDING_QUEUE) { for (int i = 0; i < table.length(); ++i) { for (ReferenceEntry<K, V> e = table.get(i); e != null; e = e.getNext()) { // Computing references aren't actually in the map yet. if (!e.getValueReference().isComputingReference()) { enqueueNotification(e, RemovalCause.EXPLICIT); } } } } for (int i = 0; i < table.length(); ++i) { table.set(i, null); } clearReferenceQueues(); evictionQueue.clear(); expirationQueue.clear(); readCount.set(0); ++modCount; count = 0; // write-volatile } finally { unlock(); postWriteCleanup(); } } }
/** * Removes an entry whose value has been garbage collected. */ 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; enqueueNotification(key, hash, valueReference.get(), RemovalCause.COLLECTED); 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(); if (!isHeldByCurrentThread()) { // don't cleanup inside of put postWriteCleanup(); } } }
void initTable(AtomicReferenceArray<E> newTable) { this.threshold = newTable.length() * 3 / 4; // 0.75 if (this.threshold == maxSegmentSize) { // prevent spurious expansion before eviction this.threshold++; } this.table = newTable; }
public final T peek() { AtomicReferenceArray<Object> buffer = this.consumerBuffer; long index = lpConsumerIndex(); int mask = this.consumerMask; Object e = lvElement(buffer, calcWrappedOffset(index, mask)); if (e == HAS_NEXT) { return newBufferPeek(lvNext(buffer), index, mask); } return e; }
public final T poll() { AtomicReferenceArray<Object> buffer = this.consumerBuffer; long index = lpConsumerIndex(); int mask = this.consumerMask; int offset = calcWrappedOffset(index, mask); Object e = lvElement(buffer, offset); boolean isNextBuffer = e == HAS_NEXT; if (e == null || isNextBuffer) { return isNextBuffer ? newBufferPoll(lvNext(buffer), index, mask) : null; } else { soConsumerIndex(1 + index); soElement(buffer, offset, null); return e; } }
/** * getAcquire returns the last value set */ public void testGetAcquireSet() { AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<>(SIZE); for (int i = 0; i < SIZE; i++) { aa.set(i, one); assertEquals(one, aa.getAcquire(i)); aa.set(i, two); assertEquals(two, aa.getAcquire(i)); aa.set(i, m3); assertEquals(m3, aa.getAcquire(i)); } }
/** Removes an entry whose value has been garbage collected. */ @CanIgnoreReturnValue boolean reclaimValue(K key, int hash, WeakValueReference<K, V, E> valueReference) { lock(); try { int newCount = this.count - 1; AtomicReferenceArray<E> table = this.table; int index = hash & (table.length() - 1); E first = table.get(index); for (E e = first; e != null; e = e.getNext()) { K entryKey = e.getKey(); if (e.getHash() == hash && entryKey != null && map.keyEquivalence.equivalent(key, entryKey)) { WeakValueReference<K, V, E> v = ((WeakValueEntry<K, V, E>) e).getValueReference(); if (v == valueReference) { ++modCount; E 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(); } }
/** * get returns the last value setPlain */ public void testGetSetPlain() { AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<>(SIZE); for (int i = 0; i < SIZE; i++) { aa.setPlain(i, one); assertEquals(one, aa.get(i)); aa.setPlain(i, two); assertEquals(two, aa.get(i)); aa.setPlain(i, m3); assertEquals(m3, aa.get(i)); } }
public void testRemoveEntry() { LocalCache<Object, Object> map = makeLocalCache(createCacheBuilder() .concurrencyLevel(1) .initialCapacity(1) .maximumSize(SMALL_MAX_SIZE) .expireAfterWrite(99999, SECONDS) .removalListener(countingRemovalListener())); Segment<Object, Object> segment = map.segments[0]; AtomicReferenceArray<ReferenceEntry<Object, Object>> table = segment.table; assertEquals(1, table.length()); Object key = new Object(); Object value = new Object(); int hash = map.hash(key); DummyEntry<Object, Object> entry = createDummyEntry(key, hash, value, null); // remove absent assertFalse(segment.removeEntry(entry, hash, RemovalCause.COLLECTED)); // remove live segment.recordWrite(entry, 1, map.ticker.read()); table.set(0, entry); segment.count = 1; assertTrue(segment.removeEntry(entry, hash, RemovalCause.COLLECTED)); assertNotificationEnqueued(map, key, value, hash); assertTrue(map.removalNotificationQueue.isEmpty()); assertFalse(segment.accessQueue.contains(entry)); assertFalse(segment.writeQueue.contains(entry)); assertEquals(0, segment.count); assertNull(table.get(0)); }
private void basicFree(long addr, int idx, AtomicReferenceArray<OffHeapStoredObjectAddressStack> freeLists) { OffHeapStoredObjectAddressStack clq = freeLists.get(idx); if (clq != null) { clq.offer(addr); } else { clq = createFreeListForEmptySlot(freeLists, idx); clq.offer(addr); if (!freeLists.compareAndSet(idx, null, clq)) { clq = freeLists.get(idx); clq.offer(addr); } } }
@CanIgnoreReturnValue V remove(Object key, int hash) { lock(); try { preWriteCleanup(); int newCount = this.count - 1; AtomicReferenceArray<E> table = this.table; int index = hash & (table.length() - 1); E first = table.get(index); for (E e = first; e != null; e = e.getNext()) { K entryKey = e.getKey(); if (e.getHash() == hash && entryKey != null && map.keyEquivalence.equivalent(key, entryKey)) { V entryValue = e.getValue(); if (entryValue != null) { // TODO(kak): Remove this branch } else if (isCollected(e)) { // TODO(kak): Remove this branch } else { return null; } ++modCount; E newFirst = removeFromChain(first, e); newCount = this.count - 1; table.set(index, newFirst); this.count = newCount; // write-volatile return entryValue; } } return null; } finally { unlock(); } }
public E poll() { long index = this.consumerIndex.get(); int offset = calcElementOffset(index); AtomicReferenceArray<E> lElementBuffer = this.buffer; E e = lvElement(lElementBuffer, offset); if (e == null) { return null; } soConsumerIndex(1 + index); soElement(lElementBuffer, offset, null); return e; }
public static void main(String[] args) { AtomicReferenceArray<Integer> x = new AtomicReferenceArray(128); Integer y = new Integer(0); for (int i = 0; i < 50000; i++) { x.getAndSet(i % x.length(), y); } }
/** * All Atomic accumulateAndGet methods throw NullPointerException * on null function argument */ public void testAccumulateAndGetNPE() { Runnable[] throwingActions = { () -> new AtomicLong().accumulateAndGet(1L, null), () -> new AtomicInteger().accumulateAndGet(1, null), () -> new AtomicReference().accumulateAndGet(one, null), () -> new AtomicLongArray(1).accumulateAndGet(0, 1L, null), () -> new AtomicIntegerArray(1).accumulateAndGet(0, 1, null), () -> new AtomicReferenceArray(1).accumulateAndGet(0, one, null), () -> aLongFieldUpdater().accumulateAndGet(this, 1L, null), () -> anIntFieldUpdater().accumulateAndGet(this, 1, null), () -> anIntegerFieldUpdater().accumulateAndGet(this, one, null), }; assertThrows(NullPointerException.class, throwingActions); }
V replace(K key, int hash, V newValue) { lock(); try { preWriteCleanup(); AtomicReferenceArray<E> table = this.table; int index = hash & (table.length() - 1); E first = table.get(index); for (E e = first; e != null; e = e.getNext()) { K entryKey = e.getKey(); if (e.getHash() == hash && entryKey != null && map.keyEquivalence.equivalent(key, entryKey)) { // If the value disappeared, this entry is partially collected, // and we should pretend like it doesn't exist. V entryValue = e.getValue(); if (entryValue == null) { if (isCollected(e)) { int newCount = this.count - 1; ++modCount; E newFirst = removeFromChain(first, e); newCount = this.count - 1; table.set(index, newFirst); this.count = newCount; // write-volatile } return null; } ++modCount; setValue(e, newValue); return entryValue; } } return null; } finally { unlock(); } }
private T newBufferPoll(AtomicReferenceArray<Object> nextBuffer, long index, int mask) { this.consumerBuffer = nextBuffer; int offsetInNew = calcWrappedOffset(index, mask); T n = lvElement(nextBuffer, offsetInNew); if (n == null) { return null; } soConsumerIndex(1 + index); soElement(nextBuffer, offsetInNew, null); return n; }