< prev index next >
src/java.base/share/classes/java/util/concurrent/atomic/Striped64.java
Print this page
8234131: Miscellaneous changes imported from jsr166 CVS 2020-12
Reviewed-by: martin
*** 123,133 ****
*/
@jdk.internal.vm.annotation.Contended static final class Cell {
volatile long value;
Cell(long x) { value = x; }
final boolean cas(long cmp, long val) {
! return VALUE.compareAndSet(this, cmp, val);
}
final void reset() {
VALUE.setVolatile(this, 0L);
}
final void reset(long identity) {
--- 123,133 ----
*/
@jdk.internal.vm.annotation.Contended static final class Cell {
volatile long value;
Cell(long x) { value = x; }
final boolean cas(long cmp, long val) {
! return VALUE.weakCompareAndSetRelease(this, cmp, val);
}
final void reset() {
VALUE.setVolatile(this, 0L);
}
final void reset(long identity) {
*** 176,186 ****
/**
* CASes the base field.
*/
final boolean casBase(long cmp, long val) {
! return BASE.compareAndSet(this, cmp, val);
}
final long getAndSetBase(long val) {
return (long)BASE.getAndSet(this, val);
}
--- 176,186 ----
/**
* CASes the base field.
*/
final boolean casBase(long cmp, long val) {
! return BASE.weakCompareAndSetRelease(this, cmp, val);
}
final long getAndSetBase(long val) {
return (long)BASE.getAndSet(this, val);
}
*** 222,255 ****
*
* @param x the value
* @param fn the update function, or null for add (this convention
* avoids the need for an extra field or function in LongAdder).
* @param wasUncontended false if CAS failed before call
*/
final void longAccumulate(long x, LongBinaryOperator fn,
! boolean wasUncontended) {
! int h;
! if ((h = getProbe()) == 0) {
ThreadLocalRandom.current(); // force initialization
! 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;
if ((rs = cells) != null &&
(m = rs.length) > 0 &&
! rs[j = (m - 1) & h] == null) {
rs[j] = r;
! break done;
}
} finally {
cellsBusy = 0;
}
continue; // Slot is now non-empty
--- 222,254 ----
*
* @param x the value
* @param fn the update function, or null for add (this convention
* avoids the need for an extra field or function in LongAdder).
* @param wasUncontended false if CAS failed before call
+ * @param index thread index from getProbe
*/
final void longAccumulate(long x, LongBinaryOperator fn,
! boolean wasUncontended, int index) {
! if (index == 0) {
ThreadLocalRandom.current(); // force initialization
! index = getProbe();
wasUncontended = true;
}
! for (boolean collide = false;;) { // True if last slot nonempty
Cell[] cs; Cell c; int n; long v;
if ((cs = cells) != null && (n = cs.length) > 0) {
! if ((c = cs[(n - 1) & index]) == 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;
if ((rs = cells) != null &&
(m = rs.length) > 0 &&
! rs[j = (m - 1) & index] == null) {
rs[j] = r;
! break;
}
} finally {
cellsBusy = 0;
}
continue; // Slot is now non-empty
*** 274,301 ****
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;
}
} finally {
cellsBusy = 0;
}
}
// Fall back on using base
else if (casBase(v = base,
(fn == null) ? v + x : fn.applyAsLong(v, x)))
! break done;
}
}
private static long apply(DoubleBinaryOperator fn, long v, double x) {
double d = Double.longBitsToDouble(v);
--- 273,300 ----
cellsBusy = 0;
}
collide = false;
continue; // Retry with expanded table
}
! index = advanceProbe(index);
}
else if (cellsBusy == 0 && cells == cs && casCellsBusy()) {
try { // Initialize table
if (cells == cs) {
Cell[] rs = new Cell[2];
! rs[index & 1] = new Cell(x);
cells = rs;
! break;
}
} finally {
cellsBusy = 0;
}
}
// Fall back on using base
else if (casBase(v = base,
(fn == null) ? v + x : fn.applyAsLong(v, x)))
! break;
}
}
private static long apply(DoubleBinaryOperator fn, long v, double x) {
double d = Double.longBitsToDouble(v);
*** 308,339 ****
* in too many places to sensibly merge with long version, given
* the low-overhead requirements of this class. So must instead be
* maintained by copy/paste/adapt.
*/
final void doubleAccumulate(double x, DoubleBinaryOperator fn,
! boolean wasUncontended) {
! int h;
! if ((h = getProbe()) == 0) {
ThreadLocalRandom.current(); // force initialization
! 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;
if ((rs = cells) != null &&
(m = rs.length) > 0 &&
! rs[j = (m - 1) & h] == null) {
rs[j] = r;
! break done;
}
} finally {
cellsBusy = 0;
}
continue; // Slot is now non-empty
--- 307,336 ----
* in too many places to sensibly merge with long version, given
* the low-overhead requirements of this class. So must instead be
* maintained by copy/paste/adapt.
*/
final void doubleAccumulate(double x, DoubleBinaryOperator fn,
! boolean wasUncontended, int index) {
! if (index == 0) {
ThreadLocalRandom.current(); // force initialization
! index = getProbe();
wasUncontended = true;
}
! for (boolean collide = false;;) { // True if last slot nonempty
Cell[] cs; Cell c; int n; long v;
if ((cs = cells) != null && (n = cs.length) > 0) {
! if ((c = cs[(n - 1) & index]) == 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;
if ((rs = cells) != null &&
(m = rs.length) > 0 &&
! rs[j = (m - 1) & index] == null) {
rs[j] = r;
! break;
}
} finally {
cellsBusy = 0;
}
continue; // Slot is now non-empty
*** 357,383 ****
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;
}
} finally {
cellsBusy = 0;
}
}
// Fall back on using base
else if (casBase(v = base, apply(fn, v, x)))
! break done;
}
}
// VarHandle mechanics
private static final VarHandle BASE;
--- 354,380 ----
cellsBusy = 0;
}
collide = false;
continue; // Retry with expanded table
}
! index = advanceProbe(index);
}
else if (cellsBusy == 0 && cells == cs && casCellsBusy()) {
try { // Initialize table
if (cells == cs) {
Cell[] rs = new Cell[2];
! rs[index & 1] = new Cell(Double.doubleToRawLongBits(x));
cells = rs;
! break;
}
} finally {
cellsBusy = 0;
}
}
// Fall back on using base
else if (casBase(v = base, apply(fn, v, x)))
! break;
}
}
// VarHandle mechanics
private static final VarHandle BASE;
< prev index next >