use of java.util.concurrent.atomic.AtomicReferenceArray in project neo4j by neo4j.
the class KernelTransactionsTest method shouldBeAbleToSnapshotDuringHeavyLoad.
@Test
public void shouldBeAbleToSnapshotDuringHeavyLoad() throws Throwable {
// GIVEN
final KernelTransactions transactions = newKernelTransactions();
Race race = new Race();
final int threads = 50;
final AtomicBoolean end = new AtomicBoolean();
final AtomicReferenceArray<KernelTransactionsSnapshot> snapshots = new AtomicReferenceArray<>(threads);
// Representing "transaction" threads
for (int i = 0; i < threads; i++) {
final int threadIndex = i;
race.addContestant(() -> {
ThreadLocalRandom random = ThreadLocalRandom.current();
while (!end.get()) {
try (KernelTransaction transaction = getKernelTransaction(transactions)) {
parkNanos(MILLISECONDS.toNanos(random.nextInt(3)));
if (snapshots.get(threadIndex) == null) {
snapshots.set(threadIndex, transactions.get());
parkNanos(MILLISECONDS.toNanos(random.nextInt(3)));
}
} catch (TransactionFailureException e) {
throw new RuntimeException(e);
}
}
});
}
// Just checks snapshots
race.addContestant(() -> {
ThreadLocalRandom random = ThreadLocalRandom.current();
int snapshotsLeft = 1_000;
while (snapshotsLeft > 0) {
int threadIndex = random.nextInt(threads);
KernelTransactionsSnapshot snapshot = snapshots.get(threadIndex);
if (snapshot != null && snapshot.allClosed()) {
snapshotsLeft--;
snapshots.set(threadIndex, null);
}
}
// End condition of this test can be described as:
// when 1000 snapshots have been seen as closed.
// setting this boolean to true will have all other threads end as well so that race.go() will end
end.set(true);
});
// WHEN
race.go();
}
use of java.util.concurrent.atomic.AtomicReferenceArray in project gocd by gocd.
the class ConcurrentHashMapV8 method internalCompute.
/**
* Implementation for compute
*/
@SuppressWarnings("unchecked")
private final Object internalCompute(K k, boolean onlyIfPresent, BiFun<? super K, ? super V, ? extends V> mf) {
int h = spread(k.hashCode());
Object val = null;
int delta = 0;
int count = 0;
for (AtomicReferenceArray<Node> tab = table; ; ) {
Node f;
int i, fh;
Object fk;
if (tab == null)
tab = initTable();
else if ((f = tabAt(tab, i = (tab.length() - 1) & h)) == null) {
if (onlyIfPresent)
break;
Node node = new Node(fh = h | LOCKED, k, null, null);
if (casTabAt(tab, i, null, node)) {
try {
count = 1;
if ((val = mf.apply(k, null)) != null) {
node.val = val;
delta = 1;
}
} finally {
if (delta == 0)
setTabAt(tab, i, null);
if (!node.casHash(fh, h)) {
node.hash = h;
synchronized (node) {
node.notifyAll();
}
;
}
}
}
if (count != 0)
break;
} else if ((fh = f.hash) == MOVED) {
if ((fk = f.key) instanceof TreeBin) {
TreeBin t = (TreeBin) fk;
t.acquire(0);
try {
if (tabAt(tab, i) == f) {
count = 1;
TreeNode p = t.getTreeNode(h, k, t.root);
Object pv;
if (p == null) {
if (onlyIfPresent)
break;
pv = null;
} else
pv = p.val;
if ((val = mf.apply(k, (V) pv)) != null) {
if (p != null)
p.val = val;
else {
count = 2;
delta = 1;
t.putTreeNode(h, k, val);
}
} else if (p != null) {
delta = -1;
t.deleteTreeNode(p);
}
}
} finally {
t.release(0);
}
if (count != 0)
break;
} else
tab = (AtomicReferenceArray<Node>) fk;
} else if ((fh & LOCKED) != 0) {
checkForResize();
f.tryAwaitLock(tab, i);
} else if (f.casHash(fh, fh | LOCKED)) {
try {
if (tabAt(tab, i) == f) {
count = 1;
for (Node e = f, pred = null; ; ++count) {
Object ek, ev;
if ((e.hash & HASH_BITS) == h && (ev = e.val) != null && ((ek = e.key) == k || k.equals(ek))) {
val = mf.apply(k, (V) ev);
if (val != null)
e.val = val;
else {
delta = -1;
Node en = e.next;
if (pred != null)
pred.next = en;
else
setTabAt(tab, i, en);
}
break;
}
pred = e;
if ((e = e.next) == null) {
if (!onlyIfPresent && (val = mf.apply(k, null)) != null) {
pred.next = new Node(h, k, val, null);
delta = 1;
if (count >= TREE_THRESHOLD)
replaceWithTreeBin(tab, i, k);
}
break;
}
}
}
} finally {
if (!f.casHash(fh | LOCKED, fh)) {
f.hash = fh;
synchronized (f) {
f.notifyAll();
}
;
}
}
if (count != 0) {
if (tab.length() <= 64)
count = 2;
break;
}
}
}
if (delta != 0) {
counter.add((long) delta);
if (count > 1)
checkForResize();
}
return val;
}
use of java.util.concurrent.atomic.AtomicReferenceArray in project gocd by gocd.
the class ConcurrentHashMapV8 method internalMerge.
/**
* Implementation for merge
*/
@SuppressWarnings("unchecked")
private final Object internalMerge(K k, V v, BiFun<? super V, ? super V, ? extends V> mf) {
int h = spread(k.hashCode());
Object val = null;
int delta = 0;
int count = 0;
for (AtomicReferenceArray<Node> tab = table; ; ) {
int i;
Node f;
int fh;
Object fk, fv;
if (tab == null)
tab = initTable();
else if ((f = tabAt(tab, i = (tab.length() - 1) & h)) == null) {
if (casTabAt(tab, i, null, new Node(h, k, v, null))) {
delta = 1;
val = v;
break;
}
} else if ((fh = f.hash) == MOVED) {
if ((fk = f.key) instanceof TreeBin) {
TreeBin t = (TreeBin) fk;
t.acquire(0);
try {
if (tabAt(tab, i) == f) {
count = 1;
TreeNode p = t.getTreeNode(h, k, t.root);
val = (p == null) ? v : mf.apply((V) p.val, v);
if (val != null) {
if (p != null)
p.val = val;
else {
count = 2;
delta = 1;
t.putTreeNode(h, k, val);
}
} else if (p != null) {
delta = -1;
t.deleteTreeNode(p);
}
}
} finally {
t.release(0);
}
if (count != 0)
break;
} else
tab = (AtomicReferenceArray<Node>) fk;
} else if ((fh & LOCKED) != 0) {
checkForResize();
f.tryAwaitLock(tab, i);
} else if (f.casHash(fh, fh | LOCKED)) {
try {
if (tabAt(tab, i) == f) {
count = 1;
for (Node e = f, pred = null; ; ++count) {
Object ek, ev;
if ((e.hash & HASH_BITS) == h && (ev = e.val) != null && ((ek = e.key) == k || k.equals(ek))) {
val = mf.apply((V) ev, v);
if (val != null)
e.val = val;
else {
delta = -1;
Node en = e.next;
if (pred != null)
pred.next = en;
else
setTabAt(tab, i, en);
}
break;
}
pred = e;
if ((e = e.next) == null) {
val = v;
pred.next = new Node(h, k, val, null);
delta = 1;
if (count >= TREE_THRESHOLD)
replaceWithTreeBin(tab, i, k);
break;
}
}
}
} finally {
if (!f.casHash(fh | LOCKED, fh)) {
f.hash = fh;
synchronized (f) {
f.notifyAll();
}
;
}
}
if (count != 0) {
if (tab.length() <= 64)
count = 2;
break;
}
}
}
if (delta != 0) {
counter.add((long) delta);
if (count > 1)
checkForResize();
}
return val;
}
use of java.util.concurrent.atomic.AtomicReferenceArray in project gocd by gocd.
the class ConcurrentHashMapV8 method internalPutIfAbsent.
/**
* Implementation for putIfAbsent
*/
private final Object internalPutIfAbsent(Object k, Object v) {
int h = spread(k.hashCode());
int count = 0;
for (AtomicReferenceArray<Node> tab = table; ; ) {
int i;
Node f;
int fh;
Object fk, fv;
if (tab == null)
tab = initTable();
else if ((f = tabAt(tab, i = (tab.length() - 1) & h)) == null) {
if (casTabAt(tab, i, null, new Node(h, k, v, null)))
break;
} else if ((fh = f.hash) == MOVED) {
if ((fk = f.key) instanceof TreeBin) {
TreeBin t = (TreeBin) fk;
Object oldVal = null;
t.acquire(0);
try {
if (tabAt(tab, i) == f) {
count = 2;
TreeNode p = t.putTreeNode(h, k, v);
if (p != null)
oldVal = p.val;
}
} finally {
t.release(0);
}
if (count != 0) {
if (oldVal != null)
return oldVal;
break;
}
} else
tab = (AtomicReferenceArray<Node>) fk;
} else if ((fh & HASH_BITS) == h && (fv = f.val) != null && ((fk = f.key) == k || k.equals(fk)))
return fv;
else {
Node g = f.next;
if (g != null) {
// at least 2 nodes -- search and maybe resize
for (Node e = g; ; ) {
Object ek, ev;
if ((e.hash & HASH_BITS) == h && (ev = e.val) != null && ((ek = e.key) == k || k.equals(ek)))
return ev;
if ((e = e.next) == null) {
checkForResize();
break;
}
}
}
if (((fh = f.hash) & LOCKED) != 0) {
checkForResize();
f.tryAwaitLock(tab, i);
} else if (tabAt(tab, i) == f && f.casHash(fh, fh | LOCKED)) {
Object oldVal = null;
try {
if (tabAt(tab, i) == f) {
count = 1;
for (Node e = f; ; ++count) {
Object ek, ev;
if ((e.hash & HASH_BITS) == h && (ev = e.val) != null && ((ek = e.key) == k || k.equals(ek))) {
oldVal = ev;
break;
}
Node last = e;
if ((e = e.next) == null) {
last.next = new Node(h, k, v, null);
if (count >= TREE_THRESHOLD)
replaceWithTreeBin(tab, i, k);
break;
}
}
}
} finally {
if (!f.casHash(fh | LOCKED, fh)) {
f.hash = fh;
synchronized (f) {
f.notifyAll();
}
;
}
}
if (count != 0) {
if (oldVal != null)
return oldVal;
if (tab.length() <= 64)
count = 2;
break;
}
}
}
}
counter.add(1L);
if (count > 1)
checkForResize();
return null;
}
use of java.util.concurrent.atomic.AtomicReferenceArray in project ignite by apache.
the class IgniteCacheCreatePutMultiNodeSelfTest method testStartNodes.
/**
* @throws Exception If failed.
*/
public void testStartNodes() throws Exception {
try {
Collection<IgniteInternalFuture<?>> futs = new ArrayList<>(GRID_CNT);
int scale = 3;
final CyclicBarrier barrier = new CyclicBarrier(GRID_CNT * scale);
final AtomicReferenceArray<Exception> err = new AtomicReferenceArray<>(GRID_CNT * scale);
for (int i = 0; i < GRID_CNT * scale; i++) {
if (i < GRID_CNT)
startGrid(i);
final int idx = i;
IgniteInternalFuture<Void> fut = GridTestUtils.runAsync(new Callable<Void>() {
@Override
public Void call() throws Exception {
Ignite ignite = ignite(idx % GRID_CNT);
try {
for (int k = 0; k < 50; k++) {
barrier.await();
String cacheName = "cache-" + k;
IgniteCache<Integer, Integer> cache = getCache(ignite, cacheName);
for (int i = 0; i < 100; i++) cache.getAndPut(i, i);
barrier.await();
ignite.destroyCache(cacheName);
}
} catch (Exception e) {
err.set(idx, e);
}
return null;
}
});
futs.add(fut);
}
for (IgniteInternalFuture<?> fut : futs) fut.get(getTestTimeout());
info("Errors: " + err);
for (int i = 0; i < err.length(); i++) {
Exception ex = err.get(i);
if (ex != null)
throw ex;
}
} finally {
stopAllGrids();
}
}
Aggregations