< prev index next >

src/java.base/share/classes/java/util/concurrent/atomic/Striped64.java

Print this page
8234131: Miscellaneous changes imported from jsr166 CVS 2021-01
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 >