< prev index next >
src/java.base/share/classes/java/util/concurrent/atomic/Striped64.java
Print this page
8192943: Optimize atomic accumulators using VarHandle getAndSet
Reviewed-by: martin, psandoz, chegar
*** 131,140 ****
--- 131,143 ----
VALUE.setVolatile(this, 0L);
}
final void reset(long identity) {
VALUE.setVolatile(this, identity);
}
+ final long getAndSet(long val) {
+ return (long)VALUE.getAndSet(this, val);
+ }
// VarHandle mechanics
private static final VarHandle VALUE;
static {
try {
*** 176,185 ****
--- 179,192 ----
*/
final boolean casBase(long cmp, long val) {
return BASE.compareAndSet(this, cmp, val);
}
+ final long getAndSetBase(long val) {
+ return (long)BASE.getAndSet(this, val);
+ }
+
/**
* CASes the cellsBusy field from 0 to 1 to acquire lock.
*/
final boolean casCellsBusy() {
return CELLSBUSY.compareAndSet(this, 0, 1);
*** 226,238 ****
h = getProbe();
wasUncontended = true;
}
boolean collide = false; // True if last slot nonempty
done: for (;;) {
! Cell[] as; Cell a; int n; long v;
! if ((as = cells) != null && (n = as.length) > 0) {
! if ((a = as[(n - 1) & h]) == null) {
if (cellsBusy == 0) { // Try to attach new Cell
Cell r = new Cell(x); // Optimistically create
if (cellsBusy == 0 && casCellsBusy()) {
try { // Recheck under lock
Cell[] rs; int m, j;
--- 233,245 ----
h = getProbe();
wasUncontended = true;
}
boolean collide = false; // True if last slot nonempty
done: for (;;) {
! Cell[] cs; Cell c; int n; long v;
! if ((cs = cells) != null && (n = cs.length) > 0) {
! if ((c = cs[(n - 1) & h]) == null) {
if (cellsBusy == 0) { // Try to attach new Cell
Cell r = new Cell(x); // Optimistically create
if (cellsBusy == 0 && casCellsBusy()) {
try { // Recheck under lock
Cell[] rs; int m, j;
*** 250,281 ****
}
collide = false;
}
else if (!wasUncontended) // CAS already known to fail
wasUncontended = true; // Continue after rehash
! else if (a.cas(v = a.value,
(fn == null) ? v + x : fn.applyAsLong(v, x)))
break;
! else if (n >= NCPU || cells != as)
collide = false; // At max size or stale
else if (!collide)
collide = true;
else if (cellsBusy == 0 && casCellsBusy()) {
try {
! if (cells == as) // Expand table unless stale
! cells = Arrays.copyOf(as, n << 1);
} finally {
cellsBusy = 0;
}
collide = false;
continue; // Retry with expanded table
}
h = advanceProbe(h);
}
! else if (cellsBusy == 0 && cells == as && casCellsBusy()) {
try { // Initialize table
! if (cells == as) {
Cell[] rs = new Cell[2];
rs[h & 1] = new Cell(x);
cells = rs;
break done;
}
--- 257,288 ----
}
collide = false;
}
else if (!wasUncontended) // CAS already known to fail
wasUncontended = true; // Continue after rehash
! else if (c.cas(v = c.value,
(fn == null) ? v + x : fn.applyAsLong(v, x)))
break;
! else if (n >= NCPU || cells != cs)
collide = false; // At max size or stale
else if (!collide)
collide = true;
else if (cellsBusy == 0 && casCellsBusy()) {
try {
! if (cells == cs) // Expand table unless stale
! cells = Arrays.copyOf(cs, n << 1);
} finally {
cellsBusy = 0;
}
collide = false;
continue; // Retry with expanded table
}
h = advanceProbe(h);
}
! else if (cellsBusy == 0 && cells == cs && casCellsBusy()) {
try { // Initialize table
! if (cells == cs) {
Cell[] rs = new Cell[2];
rs[h & 1] = new Cell(x);
cells = rs;
break done;
}
*** 310,322 ****
h = getProbe();
wasUncontended = true;
}
boolean collide = false; // True if last slot nonempty
done: for (;;) {
! Cell[] as; Cell a; int n; long v;
! if ((as = cells) != null && (n = as.length) > 0) {
! if ((a = as[(n - 1) & h]) == null) {
if (cellsBusy == 0) { // Try to attach new Cell
Cell r = new Cell(Double.doubleToRawLongBits(x));
if (cellsBusy == 0 && casCellsBusy()) {
try { // Recheck under lock
Cell[] rs; int m, j;
--- 317,329 ----
h = getProbe();
wasUncontended = true;
}
boolean collide = false; // True if last slot nonempty
done: for (;;) {
! Cell[] cs; Cell c; int n; long v;
! if ((cs = cells) != null && (n = cs.length) > 0) {
! if ((c = cs[(n - 1) & h]) == null) {
if (cellsBusy == 0) { // Try to attach new Cell
Cell r = new Cell(Double.doubleToRawLongBits(x));
if (cellsBusy == 0 && casCellsBusy()) {
try { // Recheck under lock
Cell[] rs; int m, j;
*** 334,364 ****
}
collide = false;
}
else if (!wasUncontended) // CAS already known to fail
wasUncontended = true; // Continue after rehash
! else if (a.cas(v = a.value, apply(fn, v, x)))
break;
! else if (n >= NCPU || cells != as)
collide = false; // At max size or stale
else if (!collide)
collide = true;
else if (cellsBusy == 0 && casCellsBusy()) {
try {
! if (cells == as) // Expand table unless stale
! cells = Arrays.copyOf(as, n << 1);
} finally {
cellsBusy = 0;
}
collide = false;
continue; // Retry with expanded table
}
h = advanceProbe(h);
}
! else if (cellsBusy == 0 && cells == as && casCellsBusy()) {
try { // Initialize table
! if (cells == as) {
Cell[] rs = new Cell[2];
rs[h & 1] = new Cell(Double.doubleToRawLongBits(x));
cells = rs;
break done;
}
--- 341,371 ----
}
collide = false;
}
else if (!wasUncontended) // CAS already known to fail
wasUncontended = true; // Continue after rehash
! else if (c.cas(v = c.value, apply(fn, v, x)))
break;
! else if (n >= NCPU || cells != cs)
collide = false; // At max size or stale
else if (!collide)
collide = true;
else if (cellsBusy == 0 && casCellsBusy()) {
try {
! if (cells == cs) // Expand table unless stale
! cells = Arrays.copyOf(cs, n << 1);
} finally {
cellsBusy = 0;
}
collide = false;
continue; // Retry with expanded table
}
h = advanceProbe(h);
}
! else if (cellsBusy == 0 && cells == cs && casCellsBusy()) {
try { // Initialize table
! if (cells == cs) {
Cell[] rs = new Cell[2];
rs[h & 1] = new Cell(Double.doubleToRawLongBits(x));
cells = rs;
break done;
}
< prev index next >