7 |
|
package java.util.concurrent; |
8 |
|
|
9 |
|
import java.lang.Thread.UncaughtExceptionHandler; |
10 |
+ |
import java.lang.invoke.MethodHandles; |
11 |
+ |
import java.lang.invoke.VarHandle; |
12 |
|
import java.security.AccessControlContext; |
13 |
|
import java.security.Permissions; |
14 |
|
import java.security.ProtectionDomain; |
262 |
|
* different position to use or create other queues -- they block |
263 |
|
* only when creating and registering new queues. Because it is |
264 |
|
* used only as a spinlock, unlocking requires only a "releasing" |
265 |
< |
* store (using putIntRelease). |
265 |
> |
* store (using setRelease). |
266 |
|
* |
267 |
|
* Management |
268 |
|
* ========== |
542 |
|
* Style notes |
543 |
|
* =========== |
544 |
|
* |
545 |
< |
* Memory ordering relies mainly on Unsafe intrinsics that carry |
546 |
< |
* the further responsibility of explicitly performing null- and |
547 |
< |
* bounds- checks otherwise carried out implicitly by JVMs. This |
548 |
< |
* can be awkward and ugly, but also reflects the need to control |
549 |
< |
* outcomes across the unusual cases that arise in very racy code |
550 |
< |
* with very few invariants. So these explicit checks would exist |
551 |
< |
* in some form anyway. All fields are read into locals before |
552 |
< |
* use, and null-checked if they are references. This is usually |
553 |
< |
* done in a "C"-like style of listing declarations at the heads |
554 |
< |
* of methods or blocks, and using inline assignments on first |
555 |
< |
* encounter. Array bounds-checks are usually performed by |
554 |
< |
* masking with array.length-1, which relies on the invariant that |
555 |
< |
* these arrays are created with positive lengths, which is itself |
556 |
< |
* paranoically checked. Nearly all explicit checks lead to |
557 |
< |
* bypass/return, not exception throws, because they may |
558 |
< |
* legitimately arise due to cancellation/revocation during |
559 |
< |
* shutdown. |
545 |
> |
* Memory ordering relies mainly on VarHandles This can be awkward |
546 |
> |
* and ugly, but also reflects the need to control outcomes across |
547 |
> |
* the unusual cases that arise in very racy code with very few |
548 |
> |
* invariants. So these explicit checks would exist in some form |
549 |
> |
* anyway. All fields are read into locals before use, and |
550 |
> |
* null-checked if they are references. This is usually done in a |
551 |
> |
* "C"-like style of listing declarations at the heads of methods |
552 |
> |
* or blocks, and using inline assignments on first encounter. |
553 |
> |
* Nearly all explicit checks lead to bypass/return, not exception |
554 |
> |
* throws, because they may legitimately arise due to |
555 |
> |
* cancellation/revocation during shutdown. |
556 |
|
* |
557 |
|
* There is a lot of representation-level coupling among classes |
558 |
|
* ForkJoinPool, ForkJoinWorkerThread, and ForkJoinTask. The |
748 |
|
int s = top; ForkJoinTask<?>[] a; int al, d; |
749 |
|
if ((a = array) != null && (al = a.length) > 0) { |
750 |
|
int index = (al - 1) & s; |
755 |
– |
long offset = ((long)index << ASHIFT) + ABASE; |
751 |
|
ForkJoinPool p = pool; |
752 |
|
top = s + 1; |
753 |
< |
U.putObjectRelease(a, offset, task); |
753 |
> |
QA.setRelease(a, index, task); |
754 |
|
if ((d = base - s) == 0 && p != null) { |
755 |
< |
U.fullFence(); |
755 |
> |
VarHandle.fullFence(); |
756 |
|
p.signalWork(); |
757 |
|
} |
758 |
|
else if (d + al == 1) |
778 |
|
int mask = size - 1; |
779 |
|
do { // emulate poll from old array, push to new array |
780 |
|
int index = b & oldMask; |
786 |
– |
long offset = ((long)index << ASHIFT) + ABASE; |
781 |
|
ForkJoinTask<?> x = (ForkJoinTask<?>) |
782 |
< |
U.getObjectVolatile(oldA, offset); |
782 |
> |
QA.getVolatile(oldA, index); |
783 |
|
if (x != null && |
784 |
< |
U.compareAndSwapObject(oldA, offset, x, null)) |
784 |
> |
QA.compareAndSet(oldA, index, x, null)) |
785 |
|
a[b & mask] = x; |
786 |
|
} while (++b != t); |
787 |
< |
U.storeFence(); |
787 |
> |
VarHandle.releaseFence(); |
788 |
|
} |
789 |
|
return a; |
790 |
|
} |
797 |
|
int b = base, s = top, al, i; ForkJoinTask<?>[] a; |
798 |
|
if ((a = array) != null && b != s && (al = a.length) > 0) { |
799 |
|
int index = (al - 1) & --s; |
806 |
– |
long offset = ((long)index << ASHIFT) + ABASE; |
800 |
|
ForkJoinTask<?> t = (ForkJoinTask<?>) |
801 |
< |
U.getObject(a, offset); |
801 |
> |
QA.get(a, index); |
802 |
|
if (t != null && |
803 |
< |
U.compareAndSwapObject(a, offset, t, null)) { |
803 |
> |
QA.compareAndSet(a, index, t, null)) { |
804 |
|
top = s; |
805 |
< |
U.storeFence(); |
805 |
> |
VarHandle.releaseFence(); |
806 |
|
return t; |
807 |
|
} |
808 |
|
} |
818 |
|
if ((a = array) != null && (d = b - s) < 0 && |
819 |
|
(al = a.length) > 0) { |
820 |
|
int index = (al - 1) & b; |
828 |
– |
long offset = ((long)index << ASHIFT) + ABASE; |
821 |
|
ForkJoinTask<?> t = (ForkJoinTask<?>) |
822 |
< |
U.getObjectVolatile(a, offset); |
822 |
> |
QA.getVolatile(a, index); |
823 |
|
if (b++ == base) { |
824 |
|
if (t != null) { |
825 |
< |
if (U.compareAndSwapObject(a, offset, t, null)) { |
825 |
> |
if (QA.compareAndSet(a, index, t, null)) { |
826 |
|
base = b; |
827 |
|
return t; |
828 |
|
} |
861 |
|
int b = base, s = top, al; ForkJoinTask<?>[] a; |
862 |
|
if ((a = array) != null && b != s && (al = a.length) > 0) { |
863 |
|
int index = (al - 1) & --s; |
864 |
< |
long offset = ((long)index << ASHIFT) + ABASE; |
873 |
< |
if (U.compareAndSwapObject(a, offset, task, null)) { |
864 |
> |
if (QA.compareAndSet(a, index, task, null)) { |
865 |
|
top = s; |
866 |
< |
U.storeFence(); |
866 |
> |
VarHandle.releaseFence(); |
867 |
|
return true; |
868 |
|
} |
869 |
|
} |
890 |
|
int b = base, s = top, al; ForkJoinTask<?>[] a; |
891 |
|
if ((a = array) != null && b != s && (al = a.length) > 0) { |
892 |
|
int index = (al - 1) & --s; |
902 |
– |
long offset = ((long)index << ASHIFT) + ABASE; |
893 |
|
ForkJoinTask<?> t = (ForkJoinTask<?>) |
894 |
< |
U.getAndSetObject(a, offset, null); |
894 |
> |
QA.getAndSet(a, index, null); |
895 |
|
if (t != null) { |
896 |
|
top = s; |
897 |
< |
U.storeFence(); |
897 |
> |
VarHandle.releaseFence(); |
898 |
|
t.doExec(); |
899 |
|
if (limit != 0 && --limit == 0) |
900 |
|
break; |
918 |
|
if ((a = array) != null && (d = b - s) < 0 && |
919 |
|
(al = a.length) > 0) { |
920 |
|
int index = (al - 1) & b++; |
931 |
– |
long offset = ((long)index << ASHIFT) + ABASE; |
921 |
|
ForkJoinTask<?> t = (ForkJoinTask<?>) |
922 |
< |
U.getAndSetObject(a, offset, null); |
922 |
> |
QA.getAndSet(a, index, null); |
923 |
|
if (t != null) { |
924 |
|
base = b; |
925 |
|
t.doExec(); |
945 |
|
(wa = array) != null && (wal = wa.length) > 0) { |
946 |
|
for (int m = wal - 1, ns = s - 1, i = ns; ; --i) { |
947 |
|
int index = i & m; |
959 |
– |
long offset = (index << ASHIFT) + ABASE; |
948 |
|
ForkJoinTask<?> t = (ForkJoinTask<?>) |
949 |
< |
U.getObject(wa, offset); |
949 |
> |
QA.get(wa, index); |
950 |
|
if (t == null) |
951 |
|
break; |
952 |
|
else if (t == task) { |
953 |
< |
if (U.compareAndSwapObject(wa, offset, t, null)) { |
953 |
> |
if (QA.compareAndSet(wa, index, t, null)) { |
954 |
|
top = ns; // safely shift down |
955 |
|
for (int j = i; j != ns; ++j) { |
956 |
|
ForkJoinTask<?> f; |
957 |
|
int pindex = (j + 1) & m; |
958 |
< |
long pOffset = (pindex << ASHIFT) + ABASE; |
959 |
< |
f = (ForkJoinTask<?>)U.getObject(wa, pOffset); |
972 |
< |
U.putObjectVolatile(wa, pOffset, null); |
973 |
< |
|
958 |
> |
f = (ForkJoinTask<?>)QA.get(wa, pindex); |
959 |
> |
QA.setVolatile(wa, pindex, null); |
960 |
|
int jindex = j & m; |
961 |
< |
long jOffset = (jindex << ASHIFT) + ABASE; |
976 |
< |
U.putObjectRelease(wa, jOffset, f); |
961 |
> |
QA.setRelease(wa, jindex, f); |
962 |
|
} |
963 |
< |
U.storeFence(); |
963 |
> |
VarHandle.releaseFence(); |
964 |
|
t.doExec(); |
965 |
|
} |
966 |
|
break; |
985 |
|
int b = base, s = top, al; ForkJoinTask<?>[] a; |
986 |
|
if ((a = array) != null && b != s && (al = a.length) > 0) { |
987 |
|
int index = (al - 1) & (s - 1); |
1003 |
– |
long offset = ((long)index << ASHIFT) + ABASE; |
988 |
|
ForkJoinTask<?> o = (ForkJoinTask<?>) |
989 |
< |
U.getObject(a, offset); |
989 |
> |
QA.get(a, index); |
990 |
|
if (o instanceof CountedCompleter) { |
991 |
|
CountedCompleter<?> t = (CountedCompleter<?>)o; |
992 |
|
for (CountedCompleter<?> f = t;;) { |
995 |
|
break; |
996 |
|
} |
997 |
|
else { |
998 |
< |
if (U.compareAndSwapObject(a, offset, |
1015 |
< |
t, null)) { |
998 |
> |
if (QA.compareAndSet(a, index, t, null)) { |
999 |
|
top = s - 1; |
1000 |
< |
U.storeFence(); |
1000 |
> |
VarHandle.releaseFence(); |
1001 |
|
t.doExec(); |
1002 |
|
help = true; |
1003 |
|
} |
1020 |
|
* Tries to lock shared queue by CASing phase field. |
1021 |
|
*/ |
1022 |
|
final boolean tryLockSharedQueue() { |
1023 |
< |
return U.compareAndSwapInt(this, PHASE, 0, QLOCK); |
1023 |
> |
return PHASE.compareAndSet(this, 0, QLOCK); |
1024 |
|
} |
1025 |
|
|
1026 |
|
/** |
1031 |
|
int s = top - 1, al; ForkJoinTask<?>[] a; |
1032 |
|
if ((a = array) != null && (al = a.length) > 0) { |
1033 |
|
int index = (al - 1) & s; |
1034 |
< |
long offset = ((long)index << ASHIFT) + ABASE; |
1052 |
< |
ForkJoinTask<?> t = (ForkJoinTask<?>) U.getObject(a, offset); |
1034 |
> |
ForkJoinTask<?> t = (ForkJoinTask<?>) QA.get(a, index); |
1035 |
|
if (t == task && |
1036 |
< |
U.compareAndSwapInt(this, PHASE, 0, QLOCK)) { |
1036 |
> |
PHASE.compareAndSet(this, 0, QLOCK)) { |
1037 |
|
if (top == s + 1 && array == a && |
1038 |
< |
U.compareAndSwapObject(a, offset, task, null)) { |
1038 |
> |
QA.compareAndSet(a, index, task, null)) { |
1039 |
|
popped = true; |
1040 |
|
top = s; |
1041 |
|
} |
1042 |
< |
U.putIntRelease(this, PHASE, 0); |
1042 |
> |
PHASE.setRelease(this, 0); |
1043 |
|
} |
1044 |
|
} |
1045 |
|
return popped; |
1056 |
|
int b = base, s = top, al; ForkJoinTask<?>[] a; |
1057 |
|
if ((a = array) != null && b != s && (al = a.length) > 0) { |
1058 |
|
int index = (al - 1) & (s - 1); |
1077 |
– |
long offset = ((long)index << ASHIFT) + ABASE; |
1059 |
|
ForkJoinTask<?> o = (ForkJoinTask<?>) |
1060 |
< |
U.getObject(a, offset); |
1060 |
> |
QA.get(a, index); |
1061 |
|
if (o instanceof CountedCompleter) { |
1062 |
|
CountedCompleter<?> t = (CountedCompleter<?>)o; |
1063 |
|
for (CountedCompleter<?> f = t;;) { |
1066 |
|
break; |
1067 |
|
} |
1068 |
|
else { |
1069 |
< |
if (U.compareAndSwapInt(this, PHASE, |
1089 |
< |
0, QLOCK)) { |
1069 |
> |
if (PHASE.compareAndSet(this, 0, QLOCK)) { |
1070 |
|
if (top == s && array == a && |
1071 |
< |
U.compareAndSwapObject(a, offset, |
1092 |
< |
t, null)) { |
1071 |
> |
QA.compareAndSet(a, index, t, null)) { |
1072 |
|
help = true; |
1073 |
|
top = s - 1; |
1074 |
|
} |
1075 |
< |
U.putIntRelease(this, PHASE, 0); |
1075 |
> |
PHASE.setRelease(this, 0); |
1076 |
|
if (help) |
1077 |
|
t.doExec(); |
1078 |
|
} |
1100 |
|
s != Thread.State.TIMED_WAITING); |
1101 |
|
} |
1102 |
|
|
1103 |
< |
// Unsafe mechanics. Note that some are (and must be) the same as in FJP |
1104 |
< |
private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); |
1126 |
< |
private static final long PHASE; |
1127 |
< |
private static final int ABASE; |
1128 |
< |
private static final int ASHIFT; |
1103 |
> |
// VarHandle mechanics. |
1104 |
> |
private static final VarHandle PHASE; |
1105 |
|
static { |
1106 |
|
try { |
1107 |
< |
PHASE = U.objectFieldOffset |
1108 |
< |
(WorkQueue.class.getDeclaredField("phase")); |
1133 |
< |
ABASE = U.arrayBaseOffset(ForkJoinTask[].class); |
1134 |
< |
int scale = U.arrayIndexScale(ForkJoinTask[].class); |
1135 |
< |
if ((scale & (scale - 1)) != 0) |
1136 |
< |
throw new Error("array index scale not a power of two"); |
1137 |
< |
ASHIFT = 31 - Integer.numberOfLeadingZeros(scale); |
1107 |
> |
MethodHandles.Lookup l = MethodHandles.lookup(); |
1108 |
> |
PHASE = l.findVarHandle(WorkQueue.class, "phase", int.class); |
1109 |
|
} catch (ReflectiveOperationException e) { |
1110 |
|
throw new Error(e); |
1111 |
|
} |
1285 |
|
do { |
1286 |
|
long nc = ((RC_MASK & (c + RC_UNIT)) | |
1287 |
|
(TC_MASK & (c + TC_UNIT))); |
1288 |
< |
if (ctl == c && U.compareAndSwapLong(this, CTL, c, nc)) { |
1288 |
> |
if (ctl == c && CTL.compareAndSet(this, c, nc)) { |
1289 |
|
createWorker(); |
1290 |
|
break; |
1291 |
|
} |
1384 |
|
} |
1385 |
|
if (phase != QUIET) { // else pre-adjusted |
1386 |
|
long c; // decrement counts |
1387 |
< |
do {} while (!U.compareAndSwapLong |
1388 |
< |
(this, CTL, c = ctl, ((RC_MASK & (c - RC_UNIT)) | |
1389 |
< |
(TC_MASK & (c - TC_UNIT)) | |
1390 |
< |
(SP_MASK & c)))); |
1387 |
> |
do {} while (!CTL.compareAndSet |
1388 |
> |
(this, c = ctl, ((RC_MASK & (c - RC_UNIT)) | |
1389 |
> |
(TC_MASK & (c - TC_UNIT)) | |
1390 |
> |
(SP_MASK & c)))); |
1391 |
|
} |
1392 |
|
if (w != null) |
1393 |
|
w.cancelAll(); // cancel remaining tasks |
1426 |
|
int vp = v.phase; |
1427 |
|
long nc = (v.stackPred & SP_MASK) | (UC_MASK & (c + RC_UNIT)); |
1428 |
|
Thread vt = v.owner; |
1429 |
< |
if (sp == vp && U.compareAndSwapLong(this, CTL, c, nc)) { |
1429 |
> |
if (sp == vp && CTL.compareAndSet(this, c, nc)) { |
1430 |
|
v.phase = np; |
1431 |
|
if (v.source < 0) |
1432 |
|
LockSupport.unpark(vt); |
1467 |
|
int vp = v.phase; |
1468 |
|
Thread vt = v.owner; |
1469 |
|
long nc = ((long)v.stackPred & SP_MASK) | uc; |
1470 |
< |
if (vp == sp && U.compareAndSwapLong(this, CTL, c, nc)) { |
1470 |
> |
if (vp == sp && CTL.compareAndSet(this, c, nc)) { |
1471 |
|
v.phase = np; |
1472 |
|
if (v.source < 0) |
1473 |
|
LockSupport.unpark(vt); |
1479 |
|
else if ((int)(c >> RC_SHIFT) - // reduce parallelism |
1480 |
|
(short)(bounds & SMASK) > 0) { |
1481 |
|
long nc = ((RC_MASK & (c - RC_UNIT)) | (~RC_MASK & c)); |
1482 |
< |
return U.compareAndSwapLong(this, CTL, c, nc) ? 1 : 0; |
1482 |
> |
return CTL.compareAndSet(this, c, nc) ? 1 : 0; |
1483 |
|
} |
1484 |
|
else { // validate |
1485 |
|
int md = mode, pc = md & SMASK, tc = pc + t, bc = 0; |
1518 |
|
} |
1519 |
|
|
1520 |
|
long nc = ((c + TC_UNIT) & TC_MASK) | (c & ~TC_MASK); // expand pool |
1521 |
< |
return U.compareAndSwapLong(this, CTL, c, nc) && createWorker() ? 1 : 0; |
1521 |
> |
return CTL.compareAndSet(this, c, nc) && createWorker() ? 1 : 0; |
1522 |
|
} |
1523 |
|
|
1524 |
|
/** |
1541 |
|
(a = q.array) != null && (al = a.length) > 0) { |
1542 |
|
int qid = q.id; // (never zero) |
1543 |
|
int index = (al - 1) & b; |
1573 |
– |
long offset = ((long)index << ASHIFT) + ABASE; |
1544 |
|
ForkJoinTask<?> t = (ForkJoinTask<?>) |
1545 |
< |
U.getObjectVolatile(a, offset); |
1545 |
> |
QA.getVolatile(a, index); |
1546 |
|
if (t != null && b++ == q.base && |
1547 |
< |
U.compareAndSwapObject(a, offset, t, null)) { |
1547 |
> |
QA.compareAndSet(a, index, t, null)) { |
1548 |
|
if ((q.base = b) - q.top < 0 && qid != lastSignalId) |
1549 |
|
signalWork(); // propagate signal |
1550 |
|
w.source = lastSignalId = qid; |
1579 |
|
do { |
1580 |
|
w.stackPred = (int)(c = ctl); |
1581 |
|
nc = ((c - RC_UNIT) & UC_MASK) | (SP_MASK & np); |
1582 |
< |
} while (!U.compareAndSwapLong(this, CTL, c, nc)); |
1582 |
> |
} while (!CTL.compareAndSet(this, c, nc)); |
1583 |
|
} |
1584 |
|
else { // already queued |
1585 |
|
int pred = w.stackPred; |
1606 |
|
d - System.currentTimeMillis() <= TIMEOUT_SLOP) { |
1607 |
|
long nc = ((UC_MASK & (c - TC_UNIT)) | |
1608 |
|
(SP_MASK & pred)); |
1609 |
< |
if (U.compareAndSwapLong(this, CTL, c, nc)) { |
1609 |
> |
if (CTL.compareAndSet(this, c, nc)) { |
1610 |
|
w.phase = QUIET; |
1611 |
|
return; // drop on timeout |
1612 |
|
} |
1652 |
|
(a = q.array) != null && (al = a.length) > 0) { |
1653 |
|
int qid = q.id; |
1654 |
|
int index = (al - 1) & b; |
1685 |
– |
long offset = ((long)index << ASHIFT) + ABASE; |
1655 |
|
ForkJoinTask<?> t = (ForkJoinTask<?>) |
1656 |
< |
U.getObjectVolatile(a, offset); |
1656 |
> |
QA.getVolatile(a, index); |
1657 |
|
if (t != null && b++ == q.base && id == q.source && |
1658 |
< |
U.compareAndSwapObject(a, offset, t, null)) { |
1658 |
> |
QA.compareAndSet(a, index, t, null)) { |
1659 |
|
q.base = b; |
1660 |
|
w.source = qid; |
1661 |
|
t.doExec(); |
1678 |
|
ms = 1L; // avoid 0 for timed wait |
1679 |
|
if ((block = tryCompensate(w)) != 0) { |
1680 |
|
task.internalWait(ms); |
1681 |
< |
U.getAndAddLong(this, CTL, (block > 0) ? RC_UNIT : 0L); |
1681 |
> |
CTL.getAndAdd(this, (block > 0) ? RC_UNIT : 0L); |
1682 |
|
} |
1683 |
|
s = task.status; |
1684 |
|
} |
1713 |
|
int qid = q.id; |
1714 |
|
if (released == 0) { // increment |
1715 |
|
released = 1; |
1716 |
< |
U.getAndAddLong(this, CTL, RC_UNIT); |
1716 |
> |
CTL.getAndAdd(this, RC_UNIT); |
1717 |
|
} |
1718 |
|
int index = (al - 1) & b; |
1750 |
– |
long offset = ((long)index << ASHIFT) + ABASE; |
1719 |
|
ForkJoinTask<?> t = (ForkJoinTask<?>) |
1720 |
< |
U.getObjectVolatile(a, offset); |
1720 |
> |
QA.getVolatile(a, index); |
1721 |
|
if (t != null && b++ == q.base && |
1722 |
< |
U.compareAndSwapObject(a, offset, t, null)) { |
1722 |
> |
QA.compareAndSet(a, index, t, null)) { |
1723 |
|
q.base = b; |
1724 |
|
w.source = source = q.id; |
1725 |
|
t.doExec(); |
1735 |
|
} |
1736 |
|
if (quiet) { |
1737 |
|
if (released == 0) |
1738 |
< |
U.getAndAddLong(this, CTL, RC_UNIT); |
1738 |
> |
CTL.getAndAdd(this, RC_UNIT); |
1739 |
|
w.source = prevSrc; |
1740 |
|
break; |
1741 |
|
} |
1744 |
|
w.source = source = QUIET; |
1745 |
|
if (released == 1) { // decrement |
1746 |
|
released = 0; |
1747 |
< |
U.getAndAddLong(this, CTL, RC_MASK & -RC_UNIT); |
1747 |
> |
CTL.getAndAdd(this, RC_MASK & -RC_UNIT); |
1748 |
|
} |
1749 |
|
} |
1750 |
|
} |
1779 |
|
if (b - q.top < 0 && |
1780 |
|
(a = q.array) != null && (al = a.length) > 0) { |
1781 |
|
int index = (al - 1) & b; |
1814 |
– |
long offset = ((long)index << ASHIFT) + ABASE; |
1782 |
|
ForkJoinTask<?> t = (ForkJoinTask<?>) |
1783 |
< |
U.getObjectVolatile(a, offset); |
1783 |
> |
QA.getVolatile(a, index); |
1784 |
|
if (t != null && b++ == q.base && |
1785 |
< |
U.compareAndSwapObject(a, offset, t, null)) { |
1785 |
> |
QA.compareAndSet(a, index, t, null)) { |
1786 |
|
q.base = b; |
1787 |
|
return t; |
1788 |
|
} |
2033 |
|
if (!enable || this == common) // cannot shutdown |
2034 |
|
return false; |
2035 |
|
else |
2036 |
< |
U.compareAndSwapInt(this, MODE, md, md | SHUTDOWN); |
2036 |
> |
MODE.compareAndSet(this, md, md | SHUTDOWN); |
2037 |
|
} |
2038 |
|
|
2039 |
|
while (((md = mode) & STOP) == 0) { // try to initiate termination |
2066 |
|
} |
2067 |
|
} |
2068 |
|
if ((md & STOP) == 0) |
2069 |
< |
U.compareAndSwapInt(this, MODE, md, md | STOP); |
2069 |
> |
MODE.compareAndSet(this, md, md | STOP); |
2070 |
|
} |
2071 |
|
|
2072 |
|
while (((md = mode) & TERMINATED) == 0) { // help terminate others |
2096 |
|
break; |
2097 |
|
else if ((md & SMASK) + (short)(ctl >>> TC_SHIFT) > 0) |
2098 |
|
break; |
2099 |
< |
else if (U.compareAndSwapInt(this, MODE, md, md | TERMINATED)) { |
2099 |
> |
else if (MODE.compareAndSet(this, md, md | TERMINATED)) { |
2100 |
|
synchronized (this) { |
2101 |
|
notifyAll(); // for awaitTermination |
2102 |
|
} |
3085 |
|
do {} while (!blocker.isReleasable() && |
3086 |
|
!blocker.block()); |
3087 |
|
} finally { |
3088 |
< |
U.getAndAddLong(p, CTL, (block > 0) ? RC_UNIT : 0L); |
3088 |
> |
CTL.getAndAdd(p, (block > 0) ? RC_UNIT : 0L); |
3089 |
|
} |
3090 |
|
break; |
3091 |
|
} |
3121 |
|
if ((a = w.array) != null && (d = b - s) < 0 && |
3122 |
|
(al = a.length) > 0) { |
3123 |
|
int index = (al - 1) & b; |
3157 |
– |
long offset = ((long)index << ASHIFT) + ABASE; |
3124 |
|
ForkJoinTask<?> t = (ForkJoinTask<?>) |
3125 |
< |
U.getObjectVolatile(a, offset); |
3125 |
> |
QA.getVolatile(a, index); |
3126 |
|
if (blocker.isReleasable()) |
3127 |
|
break; |
3128 |
|
else if (b++ == w.base) { |
3133 |
|
else if (!(t instanceof CompletableFuture. |
3134 |
|
AsynchronousCompletionTask)) |
3135 |
|
break; |
3136 |
< |
else if (U.compareAndSwapObject(a, offset, |
3171 |
< |
t, null)) { |
3136 |
> |
else if (QA.compareAndSet(a, index, t, null)) { |
3137 |
|
w.base = b; |
3138 |
|
t.doExec(); |
3139 |
|
} |
3158 |
|
return new ForkJoinTask.AdaptedCallable<T>(callable); |
3159 |
|
} |
3160 |
|
|
3161 |
< |
// Unsafe mechanics |
3162 |
< |
private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); |
3163 |
< |
private static final long CTL; |
3164 |
< |
private static final long MODE; |
3200 |
< |
private static final int ABASE; |
3201 |
< |
private static final int ASHIFT; |
3161 |
> |
// VarHandle mechanics |
3162 |
> |
private static final VarHandle CTL; |
3163 |
> |
private static final VarHandle MODE; |
3164 |
> |
private static final VarHandle QA; |
3165 |
|
|
3166 |
|
static { |
3167 |
|
try { |
3168 |
< |
CTL = U.objectFieldOffset |
3169 |
< |
(ForkJoinPool.class.getDeclaredField("ctl")); |
3170 |
< |
MODE = U.objectFieldOffset |
3171 |
< |
(ForkJoinPool.class.getDeclaredField("mode")); |
3209 |
< |
ABASE = U.arrayBaseOffset(ForkJoinTask[].class); |
3210 |
< |
int scale = U.arrayIndexScale(ForkJoinTask[].class); |
3211 |
< |
if ((scale & (scale - 1)) != 0) |
3212 |
< |
throw new Error("array index scale not a power of two"); |
3213 |
< |
ASHIFT = 31 - Integer.numberOfLeadingZeros(scale); |
3168 |
> |
MethodHandles.Lookup l = MethodHandles.lookup(); |
3169 |
> |
CTL = l.findVarHandle(ForkJoinPool.class, "ctl", long.class); |
3170 |
> |
MODE = l.findVarHandle(ForkJoinPool.class, "mode", int.class); |
3171 |
> |
QA = MethodHandles.arrayElementVarHandle(ForkJoinTask[].class); |
3172 |
|
} catch (ReflectiveOperationException e) { |
3173 |
|
throw new Error(e); |
3174 |
|
} |