739 |
|
static final int FIFO_QUEUE = 1 << 16; |
740 |
|
static final int SHARED_QUEUE = 1 << 31; // must be negative |
741 |
|
|
742 |
+ |
// This version uses array access methods in anticipation of JDK9 support |
743 |
+ |
// that should eliminate their need |
744 |
+ |
|
745 |
+ |
static final ForkJoinTask<?> getAt(ForkJoinTask<?>[] a, int i) { |
746 |
+ |
return (ForkJoinTask<?>)U.getObjectVolatile( |
747 |
+ |
a, (long)((i << ASHIFT) + ABASE)); |
748 |
+ |
} |
749 |
+ |
|
750 |
+ |
static final void setAt(ForkJoinTask<?>[] a, int i, ForkJoinTask<?> x) { |
751 |
+ |
U.putOrderedObject(a, (long)((i << ASHIFT) + ABASE), x); |
752 |
+ |
} |
753 |
+ |
|
754 |
+ |
static final boolean casAt(ForkJoinTask<?>[] a, int i, |
755 |
+ |
ForkJoinTask<?> c, ForkJoinTask<?> v) { |
756 |
+ |
return U.compareAndSwapObject( |
757 |
+ |
a, (long)((i << ASHIFT) + ABASE), c, v); |
758 |
+ |
} |
759 |
+ |
|
760 |
+ |
static final ForkJoinTask<?> xchgAt(ForkJoinTask<?>[] a, int i, |
761 |
+ |
ForkJoinTask<?> x) { |
762 |
+ |
return (ForkJoinTask<?>)U.getAndSetObject( |
763 |
+ |
a, (long)((i << ASHIFT) + ABASE), x); |
764 |
+ |
} |
765 |
+ |
|
766 |
|
/** |
767 |
|
* Queues supporting work-stealing as well as external task |
768 |
|
* submission. See above for descriptions and algorithms. |
811 |
|
volatile ForkJoinTask<?> currentJoin; // task being joined in awaitJoin |
812 |
|
volatile ForkJoinTask<?> currentSteal; // mainly used by helpStealer |
813 |
|
|
814 |
+ |
// Temporary repeats of array access methods |
815 |
+ |
|
816 |
+ |
static final ForkJoinTask<?> getAt(ForkJoinTask<?>[] a, int i) { |
817 |
+ |
return (ForkJoinTask<?>)U.getObjectVolatile( |
818 |
+ |
a, (long)((i << ASHIFT) + ABASE)); |
819 |
+ |
} |
820 |
+ |
|
821 |
+ |
static final void setAt(ForkJoinTask<?>[] a, int i, ForkJoinTask<?> x) { |
822 |
+ |
U.putOrderedObject(a, (long)((i << ASHIFT) + ABASE), x); |
823 |
+ |
} |
824 |
+ |
|
825 |
+ |
static final boolean casAt(ForkJoinTask<?>[] a, int i, |
826 |
+ |
ForkJoinTask<?> c, ForkJoinTask<?> v) { |
827 |
+ |
return U.compareAndSwapObject( |
828 |
+ |
a, (long)((i << ASHIFT) + ABASE), c, v); |
829 |
+ |
} |
830 |
+ |
|
831 |
+ |
static final ForkJoinTask<?> xchgAt(ForkJoinTask<?>[] a, int i, |
832 |
+ |
ForkJoinTask<?> x) { |
833 |
+ |
return (ForkJoinTask<?>)U.getAndSetObject( |
834 |
+ |
a, (long)((i << ASHIFT) + ABASE), x); |
835 |
+ |
} |
836 |
+ |
|
837 |
+ |
|
838 |
|
WorkQueue(ForkJoinPool pool, ForkJoinWorkerThread owner) { |
839 |
|
this.pool = pool; |
840 |
|
this.owner = owner; |
863 |
|
* near-empty queue has at least one unclaimed task. |
864 |
|
*/ |
865 |
|
final boolean isEmpty() { |
866 |
< |
ForkJoinTask<?>[] a; int n, m, s; |
866 |
> |
ForkJoinTask<?>[] a; int n, al, s; |
867 |
|
return ((n = base - (s = top)) >= 0 || |
868 |
|
(n == -1 && // possibly one task |
869 |
< |
((a = array) == null || (m = a.length - 1) < 0 || |
870 |
< |
U.getObject |
823 |
< |
(a, (long)((m & (s - 1)) << ASHIFT) + ABASE) == null))); |
869 |
> |
((a = array) == null || (al = a.length) == 0 || |
870 |
> |
getAt(a, (al - 1) & (s - 1)) == null))); |
871 |
|
} |
872 |
|
|
873 |
|
/** |
879 |
|
*/ |
880 |
|
final void push(ForkJoinTask<?> task) { |
881 |
|
ForkJoinTask<?>[] a; ForkJoinPool p; |
882 |
< |
if ((a = array) != null) { // ignore if no queue |
882 |
> |
if ((a = array) != null) { // ignore if queue removed |
883 |
|
int b = base, m = a.length - 1, s = top, n; |
884 |
< |
long j = ((m & s) << ASHIFT) + ABASE; |
885 |
< |
if (m >= 0) { |
839 |
< |
U.putOrderedObject(a, j, task); |
884 |
> |
if (m > 0) { // always true, but check required |
885 |
> |
setAt(a, m & s, task); |
886 |
|
U.putOrderedInt(this, QTOP, s + 1); |
887 |
|
if ((n = s - b) <= 1) { |
888 |
|
if ((p = pool) != null) |
902 |
|
final ForkJoinTask<?>[] growArray() { |
903 |
|
ForkJoinTask<?>[] oldA = array; |
904 |
|
int size = oldA != null ? oldA.length << 1 : INITIAL_QUEUE_CAPACITY; |
905 |
< |
if (size < 0 || size > MAXIMUM_QUEUE_CAPACITY) |
905 |
> |
if (size < INITIAL_QUEUE_CAPACITY || size > MAXIMUM_QUEUE_CAPACITY) |
906 |
|
throw new RejectedExecutionException("Queue capacity exceeded"); |
907 |
|
int oldMask, t, b; |
908 |
|
ForkJoinTask<?>[] a = array = new ForkJoinTask<?>[size]; |
909 |
< |
if (oldA != null && (oldMask = oldA.length - 1) >= 0 && |
909 |
> |
if (oldA != null && (oldMask = oldA.length - 1) > 0 && |
910 |
|
(t = top) - (b = base) > 0) { |
911 |
|
int mask = size - 1; |
912 |
|
do { // emulate poll from old array, push to new array |
913 |
|
ForkJoinTask<?> x; |
914 |
< |
long oldj = ((b & oldMask) << ASHIFT) + ABASE; |
915 |
< |
long j = ((b & mask) << ASHIFT) + ABASE; |
916 |
< |
x = (ForkJoinTask<?>)U.getObjectVolatile(oldA, oldj); |
917 |
< |
if (x != null && |
872 |
< |
U.compareAndSwapObject(oldA, oldj, x, null)) |
873 |
< |
U.putObjectVolatile(a, j, x); |
914 |
> |
int oldj = b & oldMask, j = b & mask; |
915 |
> |
if ((x = getAt(oldA, oldj)) != null && |
916 |
> |
casAt(oldA, oldj, x, null)) |
917 |
> |
setAt(a, j, x); |
918 |
|
} while (++b != t); |
919 |
|
} |
920 |
|
return a; |
925 |
|
* by owner in unshared queues. |
926 |
|
*/ |
927 |
|
final ForkJoinTask<?> pop() { |
928 |
< |
ForkJoinTask<?>[] a; ForkJoinTask<?> t; int m; |
929 |
< |
if ((a = array) != null && (m = a.length - 1) >= 0) { |
928 |
> |
ForkJoinTask<?>[] a; ForkJoinTask<?> t; int al; |
929 |
> |
if ((a = array) != null && (al = a.length) > 0) { |
930 |
|
for (int s; (s = top - 1) - base >= 0;) { |
931 |
< |
long j = ((m & s) << ASHIFT) + ABASE; |
932 |
< |
if ((t = (ForkJoinTask<?>)U.getObject(a, j)) == null) |
931 |
> |
int j = (al - 1) & s; |
932 |
> |
if ((t = getAt(a, j)) == null) |
933 |
|
break; |
934 |
< |
if (U.compareAndSwapObject(a, j, t, null)) { |
934 |
> |
if (casAt(a, j, t, null)) { |
935 |
|
U.putOrderedInt(this, QTOP, s); |
936 |
|
return t; |
937 |
|
} |
948 |
|
final ForkJoinTask<?> pollAt(int b) { |
949 |
|
ForkJoinTask<?> t; ForkJoinTask<?>[] a; |
950 |
|
if ((a = array) != null) { |
951 |
< |
int m = a.length - 1; |
952 |
< |
long j = ((m & b) << ASHIFT) + ABASE; |
953 |
< |
if (m >= 0 && |
910 |
< |
(t = (ForkJoinTask<?>)U.getObjectVolatile(a, j)) != null && |
911 |
< |
base == b && U.compareAndSwapObject(a, j, t, null)) { |
951 |
> |
int al = a.length, j = (al - 1) & b; |
952 |
> |
if (al > 0 && (t = getAt(a, j)) != null && |
953 |
> |
base == b && casAt(a, j, t, null)) { |
954 |
|
base = b + 1; |
955 |
|
return t; |
956 |
|
} |
962 |
|
* Takes next task, if one exists, in FIFO order. |
963 |
|
*/ |
964 |
|
final ForkJoinTask<?> poll() { |
965 |
< |
ForkJoinTask<?>[] a; int b; ForkJoinTask<?> t; |
966 |
< |
while ((b = base) - top < 0 && (a = array) != null) { |
967 |
< |
int m = a.length - 1; |
968 |
< |
long j = ((m & b) << ASHIFT) + ABASE; |
927 |
< |
if (m < 0) |
928 |
< |
break; |
929 |
< |
t = (ForkJoinTask<?>)U.getObjectVolatile(a, j); |
965 |
> |
ForkJoinTask<?>[] a; int b, al, j; |
966 |
> |
while ((b = base) - top < 0 && (a = array) != null && |
967 |
> |
(al = a.length) > 0) { |
968 |
> |
ForkJoinTask<?> t = getAt(a, j = (al - 1) & b); |
969 |
|
if (base == b) { |
970 |
|
if (t != null) { |
971 |
< |
if (U.compareAndSwapObject(a, j, t, null)) { |
971 |
> |
if (casAt(a, j, t, null)) { |
972 |
|
base = b + 1; |
973 |
|
return t; |
974 |
|
} |
991 |
|
* Returns next task, if one exists, in order specified by mode. |
992 |
|
*/ |
993 |
|
final ForkJoinTask<?> peek() { |
994 |
< |
ForkJoinTask<?>[] a = array; int m; |
995 |
< |
if (a == null || (m = a.length - 1) < 0) |
996 |
< |
return null; |
997 |
< |
int i = (config & FIFO_QUEUE) == 0 ? top - 1 : base; |
998 |
< |
long j = ((i & m) << ASHIFT) + ABASE; |
999 |
< |
return (ForkJoinTask<?>)U.getObjectVolatile(a, j); |
994 |
> |
ForkJoinTask<?>[] a = array; int al; |
995 |
> |
if (a != null && (al = a.length) > 0) { |
996 |
> |
int i = (config & FIFO_QUEUE) == 0 ? top - 1 : base; |
997 |
> |
return getAt(a, (al - 1) & i); |
998 |
> |
} |
999 |
> |
return null; |
1000 |
|
} |
1001 |
|
|
1002 |
|
/** |
1006 |
|
final boolean tryUnpush(ForkJoinTask<?> t) { |
1007 |
|
ForkJoinTask<?>[] a; |
1008 |
|
if ((a = array) != null) { |
1009 |
< |
int b = base, m = a.length - 1, s = top; |
1010 |
< |
long j = ((m & (s - 1)) << ASHIFT) + ABASE; |
1011 |
< |
if (s != b && m >= 0 && |
973 |
< |
U.compareAndSwapObject(a, j, t, null)) { |
1009 |
> |
int b = base, al = a.length, s = top; |
1010 |
> |
if (s != b && al > 0 && |
1011 |
> |
casAt(a, (al - 1) & (s - 1), t, null)) { |
1012 |
|
U.putOrderedInt(this, QTOP, s - 1); |
1013 |
|
return true; |
1014 |
|
} |
1044 |
|
} |
1045 |
|
|
1046 |
|
/** |
1047 |
< |
* Removes and executes all local tasks. If LIFO, invokes |
1048 |
< |
* pollAndExecAll. Otherwise implements a specialized pop loop |
1049 |
< |
* to exec until empty. |
1050 |
< |
*/ |
1051 |
< |
final void execLocalTasks() { |
1052 |
< |
int b = base, m, s; |
1053 |
< |
ForkJoinTask<?>[] a = array; |
1054 |
< |
if (b - (s = top - 1) <= 0 && a != null && |
1055 |
< |
(m = a.length - 1) >= 0) { |
1056 |
< |
if ((config & FIFO_QUEUE) == 0) { |
1019 |
< |
for (ForkJoinTask<?> t;;) { |
1020 |
< |
long j = ((m & s) << ASHIFT) + ABASE; |
1021 |
< |
if ((t = (ForkJoinTask<?>)U.getAndSetObject |
1022 |
< |
(a, j, null)) == null) |
1023 |
< |
break; |
1024 |
< |
U.putOrderedInt(this, QTOP, s); |
1025 |
< |
t.doExec(); |
1026 |
< |
if (base - (s = top - 1) > 0) |
1027 |
< |
break; |
1028 |
< |
} |
1047 |
> |
* Pops and runs tasks until empty. |
1048 |
> |
*/ |
1049 |
> |
final void popAndExecAll() { |
1050 |
> |
ForkJoinTask<?>[] a; ForkJoinTask<?> t; |
1051 |
> |
while ((a = array) != null) { |
1052 |
> |
int b = base, al = a.length, s = top, i = (al - 1) & (s - 1); |
1053 |
> |
if (b != s && al > 0 && |
1054 |
> |
(t = xchgAt(a, i, null)) != null) { |
1055 |
> |
U.putOrderedInt(this, QTOP, s - 1); |
1056 |
> |
t.doExec(); |
1057 |
|
} |
1058 |
|
else |
1059 |
< |
pollAndExecAll(); |
1059 |
> |
break; |
1060 |
|
} |
1061 |
|
} |
1062 |
|
|
1068 |
|
scanState &= ~SCANNING; // mark as busy |
1069 |
|
(currentSteal = task).doExec(); |
1070 |
|
U.putOrderedObject(this, QCURRENTSTEAL, null); // release for GC |
1071 |
< |
execLocalTasks(); |
1071 |
> |
if ((config & FIFO_QUEUE) != 0) |
1072 |
> |
pollAndExecAll(); |
1073 |
> |
else |
1074 |
> |
popAndExecAll(); |
1075 |
|
ForkJoinWorkerThread thread = owner; |
1076 |
|
if (++nsteals < 0) // collect on overflow |
1077 |
|
transferStealCount(pool); |
1100 |
|
* @return true if queue empty and task not known to be done |
1101 |
|
*/ |
1102 |
|
final boolean tryRemoveAndExec(ForkJoinTask<?> task) { |
1103 |
< |
ForkJoinTask<?>[] a; int m, s, b, n; |
1104 |
< |
if ((a = array) != null && (m = a.length - 1) >= 0 && |
1074 |
< |
task != null) { |
1103 |
> |
ForkJoinTask<?>[] a; int al, s, b, n; |
1104 |
> |
if ((a = array) != null && (al = a.length) > 0 && task != null) { |
1105 |
|
while ((n = (s = top) - (b = base)) > 0) { |
1106 |
|
for (ForkJoinTask<?> t;;) { // traverse from s to b |
1107 |
< |
long j = ((--s & m) << ASHIFT) + ABASE; |
1108 |
< |
if ((t = (ForkJoinTask<?>)U.getObject(a, j)) == null) |
1107 |
> |
int j = --s & (al - 1); |
1108 |
> |
if ((t = getAt(a, j)) == null) |
1109 |
|
return s + 1 == top; // shorter than expected |
1110 |
|
else if (t == task) { |
1111 |
|
boolean removed = false; |
1112 |
|
if (s + 1 == top) { // pop |
1113 |
< |
if (U.compareAndSwapObject(a, j, task, null)) { |
1113 |
> |
if (casAt(a, j, task, null)) { |
1114 |
|
U.putOrderedInt(this, QTOP, s); |
1115 |
|
removed = true; |
1116 |
|
} |
1117 |
|
} |
1118 |
|
else if (base == b) // replace with proxy |
1119 |
< |
removed = U.compareAndSwapObject( |
1090 |
< |
a, j, task, new EmptyTask()); |
1119 |
> |
removed = casAt(a, j, task, new EmptyTask()); |
1120 |
|
if (removed) |
1121 |
|
task.doExec(); |
1122 |
|
break; |
1123 |
|
} |
1124 |
|
else if (t.status < 0 && s + 1 == top) { |
1125 |
< |
if (U.compareAndSwapObject(a, j, t, null)) |
1125 |
> |
if (casAt(a, j, t, null)) |
1126 |
|
U.putOrderedInt(this, QTOP, s); |
1127 |
|
break; // was cancelled |
1128 |
|
} |
1141 |
|
* in either shared or owned mode. Used only by helpComplete. |
1142 |
|
*/ |
1143 |
|
final CountedCompleter<?> popCC(CountedCompleter<?> task, int mode) { |
1144 |
< |
int s; ForkJoinTask<?>[] a; Object o; |
1145 |
< |
if (base - (s = top) < 0 && (a = array) != null) { |
1146 |
< |
int m = a.length - 1; |
1147 |
< |
long j = ((m & (s - 1)) << ASHIFT) + ABASE; |
1148 |
< |
if (m >= 0 && (o = U.getObjectVolatile(a, j)) != null && |
1120 |
< |
(o instanceof CountedCompleter)) { |
1144 |
> |
ForkJoinTask<?>[] a; ForkJoinTask<?> o; |
1145 |
> |
if ((a = array) != null) { |
1146 |
> |
int b = base, al = a.length, s = top, i = (al - 1) & (s - 1); |
1147 |
> |
if (b != s && al > 0 && |
1148 |
> |
((o = a[i]) instanceof CountedCompleter)) { |
1149 |
|
CountedCompleter<?> t = (CountedCompleter<?>)o; |
1150 |
|
for (CountedCompleter<?> r = t;;) { |
1151 |
|
if (r == task) { |
1152 |
|
if (mode < 0) { // must lock |
1153 |
|
if (U.compareAndSwapInt(this, QLOCK, 0, 1)) { |
1154 |
|
if (top == s && array == a && |
1155 |
< |
U.compareAndSwapObject(a, j, t, null)) { |
1155 |
> |
casAt(a, i, t, null)) { |
1156 |
|
U.putOrderedInt(this, QTOP, s - 1); |
1157 |
|
U.putOrderedInt(this, QLOCK, 0); |
1158 |
|
return t; |
1160 |
|
U.compareAndSwapInt(this, QLOCK, 1, 0); |
1161 |
|
} |
1162 |
|
} |
1163 |
< |
else if (U.compareAndSwapObject(a, j, t, null)) { |
1163 |
> |
else if (casAt(a, i, t, null)) { |
1164 |
|
U.putOrderedInt(this, QTOP, s - 1); |
1165 |
|
return t; |
1166 |
|
} |
1185 |
|
* the base index, forced negative. |
1186 |
|
*/ |
1187 |
|
final int pollAndExecCC(CountedCompleter<?> task) { |
1188 |
< |
int b, h; ForkJoinTask<?>[] a; Object o; |
1189 |
< |
if ((b = base) - top >= 0 || (a = array) == null) |
1188 |
> |
int b, h, j, al; ForkJoinTask<?>[] a; Object o; |
1189 |
> |
if ((b = base) - top >= 0 || (a = array) == null || |
1190 |
> |
(al = a.length) <= 0) |
1191 |
|
h = b | Integer.MIN_VALUE; // to sense movement on re-poll |
1192 |
+ |
else if ((o = getAt(a, j = (al - 1) & b)) == null) |
1193 |
+ |
h = 2; // retryable |
1194 |
+ |
else if (!(o instanceof CountedCompleter)) |
1195 |
+ |
h = -1; // unmatchable |
1196 |
|
else { |
1197 |
< |
int m = a.length - 1; |
1198 |
< |
long j = ((m & b) << ASHIFT) + ABASE; |
1199 |
< |
if (m < 0 || (o = U.getObjectVolatile(a, j)) == null) |
1200 |
< |
h = 2; // retryable |
1201 |
< |
else if (!(o instanceof CountedCompleter)) |
1202 |
< |
h = -1; // unmatchable |
1203 |
< |
else { |
1171 |
< |
CountedCompleter<?> t = (CountedCompleter<?>)o; |
1172 |
< |
for (CountedCompleter<?> r = t;;) { |
1173 |
< |
if (r == task) { |
1174 |
< |
if (base == b && |
1175 |
< |
U.compareAndSwapObject(a, j, t, null)) { |
1176 |
< |
base = b + 1; |
1177 |
< |
t.doExec(); |
1178 |
< |
h = 1; // success |
1179 |
< |
} |
1180 |
< |
else |
1181 |
< |
h = 2; // lost CAS |
1182 |
< |
break; |
1183 |
< |
} |
1184 |
< |
else if ((r = r.completer) == null) { |
1185 |
< |
h = -1; // unmatched |
1186 |
< |
break; |
1197 |
> |
CountedCompleter<?> t = (CountedCompleter<?>)o; |
1198 |
> |
for (CountedCompleter<?> r = t;;) { |
1199 |
> |
if (r == task) { |
1200 |
> |
if (base == b && casAt(a, j, t, null)) { |
1201 |
> |
base = b + 1; |
1202 |
> |
t.doExec(); |
1203 |
> |
h = 1; // success |
1204 |
|
} |
1205 |
+ |
else |
1206 |
+ |
h = 2; // lost CAS |
1207 |
+ |
break; |
1208 |
+ |
} |
1209 |
+ |
else if ((r = r.completer) == null) { |
1210 |
+ |
h = -1; // unmatched |
1211 |
+ |
break; |
1212 |
|
} |
1213 |
|
} |
1214 |
|
} |
1727 |
|
if ((ws = workQueues) != null && (m = ws.length - 1) > 0 && w != null) { |
1728 |
|
int ss = w.scanState; // initially non-negative |
1729 |
|
for (int origin = r & m, k = origin, oldSum = 0, checkSum = 0;;) { |
1730 |
< |
WorkQueue q; ForkJoinTask<?>[] a; ForkJoinTask<?> t; |
1707 |
< |
int b, am, n; long c; |
1730 |
> |
WorkQueue q; ForkJoinTask<?> t; int al, i, n; long c; |
1731 |
|
if ((q = ws[k]) != null) { |
1732 |
< |
if ((n = (b = q.base) - q.top) < 0 && // non-empty |
1733 |
< |
(a = q.array) != null) { |
1734 |
< |
long i = (((am = a.length - 1) & b) << ASHIFT) + ABASE; |
1735 |
< |
if (am >= 0 && |
1713 |
< |
(t = ((ForkJoinTask<?>) |
1714 |
< |
U.getObjectVolatile(a, i))) != null && |
1732 |
> |
int b = q.base; ForkJoinTask<?>[] a = q.array; |
1733 |
> |
if ((n = b - q.top) < 0 && a != null && |
1734 |
> |
(al = a.length) > 0) { // non-empty |
1735 |
> |
if ((t = getAt(a, i = (al - 1) & b)) != null && |
1736 |
|
q.base == b) { |
1737 |
|
if (ss >= 0) { |
1738 |
< |
if (U.compareAndSwapObject(a, i, t, null)) { |
1738 |
> |
if (casAt(a, i, t, null)) { |
1739 |
|
q.base = b + 1; |
1740 |
|
if (n < -1) // signal others |
1741 |
|
signalWork(ws, q); |
1864 |
|
final int helpComplete(WorkQueue w, CountedCompleter<?> task, |
1865 |
|
int maxTasks) { |
1866 |
|
WorkQueue[] ws; int s = 0, m; |
1867 |
< |
if ((ws = workQueues) != null && (m = ws.length - 1) >= 0 && |
1867 |
> |
if ((ws = workQueues) != null && (m = ws.length - 1) > 0 && |
1868 |
|
task != null && w != null) { |
1869 |
|
int mode = w.config; // for popCC |
1870 |
|
int r = w.hint ^ w.top; // arbitrary seed for origin |
1920 |
|
private void helpStealer(WorkQueue w, ForkJoinTask<?> task) { |
1921 |
|
WorkQueue[] ws = workQueues; |
1922 |
|
int oldSum = 0, checkSum, m; |
1923 |
< |
if (ws != null && (m = ws.length - 1) >= 0 && w != null && |
1923 |
> |
if (ws != null && (m = ws.length - 1) > 0 && w != null && |
1924 |
|
task != null) { |
1925 |
|
do { // restart point |
1926 |
|
checkSum = 0; // for stability check |
1939 |
|
} |
1940 |
|
} |
1941 |
|
for (;;) { // help v or descend |
1942 |
< |
ForkJoinTask<?>[] a; int b, am; |
1942 |
> |
ForkJoinTask<?>[] a; int b, al, i; |
1943 |
|
checkSum += (b = v.base); |
1944 |
|
ForkJoinTask<?> next = v.currentJoin; |
1945 |
|
if (subtask.status < 0 || j.currentJoin != subtask || |
1946 |
|
v.currentSteal != subtask) // stale |
1947 |
|
break descent; |
1948 |
|
if (b - v.top >= 0 || (a = v.array) == null || |
1949 |
< |
(am = a.length - 1) < 0) { |
1949 |
> |
(al = a.length) <= 0) { |
1950 |
|
if ((subtask = next) == null) |
1951 |
|
break descent; |
1952 |
|
j = v; |
1953 |
|
break; |
1954 |
|
} |
1955 |
< |
long i = ((am & b) << ASHIFT) + ABASE; |
1935 |
< |
ForkJoinTask<?> t = ((ForkJoinTask<?>) |
1936 |
< |
U.getObjectVolatile(a, i)); |
1955 |
> |
ForkJoinTask<?> t = getAt(a, i = (al - 1) & b); |
1956 |
|
if (v.base == b) { |
1957 |
|
if (t == null) // stale |
1958 |
|
break descent; |
1959 |
< |
if (U.compareAndSwapObject(a, i, t, null)) { |
1959 |
> |
if (casAt(a, i, t, null)) { |
1960 |
|
v.base = b + 1; |
1961 |
|
ForkJoinTask<?> ps = w.currentSteal; |
1962 |
|
int top = w.top; |
2081 |
|
private WorkQueue findNonEmptyStealQueue() { |
2082 |
|
WorkQueue[] ws; int m; // one-shot version of scan loop |
2083 |
|
int r = ThreadLocalRandom.nextSecondarySeed(); |
2084 |
< |
if ((ws = workQueues) != null && (m = ws.length - 1) >= 0) { |
2084 |
> |
if ((ws = workQueues) != null && (m = ws.length - 1) > 0) { |
2085 |
|
for (int origin = r & m, k = origin, oldSum = 0, checkSum = 0;;) { |
2086 |
|
WorkQueue q; int b; |
2087 |
|
if ((q = ws[k]) != null) { |
2109 |
|
ForkJoinTask<?> ps = w.currentSteal; // save context |
2110 |
|
for (boolean active = true;;) { |
2111 |
|
long c; WorkQueue q; ForkJoinTask<?> t; int b; |
2112 |
< |
w.execLocalTasks(); // run locals before each scan |
2112 |
> |
if ((w.config & FIFO_QUEUE) != 0) |
2113 |
> |
w.pollAndExecAll(); // run locals before each scan |
2114 |
> |
else |
2115 |
> |
w.popAndExecAll(); |
2116 |
|
if ((q = findNonEmptyStealQueue()) != null) { |
2117 |
|
if (!active) { // re-establish active count |
2118 |
|
active = true; |
2338 |
|
throw new RejectedExecutionException(); |
2339 |
|
} |
2340 |
|
else if ((rs & STARTED) == 0 || // initialize |
2341 |
< |
((ws = workQueues) == null || (m = ws.length - 1) < 0)) { |
2341 |
> |
((ws = workQueues) == null || (m = ws.length - 1) <= 0)) { |
2342 |
|
int ns = 0; |
2343 |
|
rs = lockRunState(); |
2344 |
|
try { |
2360 |
|
else if ((q = ws[k = r & m & SQMASK]) != null) { |
2361 |
|
if (q.qlock == 0 && U.compareAndSwapInt(q, QLOCK, 0, 1)) { |
2362 |
|
ForkJoinTask<?>[] a = q.array; |
2363 |
< |
int s = q.top, am; |
2363 |
> |
int s = q.top; |
2364 |
|
boolean submitted = false; // initial submission or resizing |
2365 |
|
try { // locked version of push |
2366 |
< |
if (((a != null && a.length > s + 1 - q.base) || |
2367 |
< |
(a = q.growArray()) != null) && |
2368 |
< |
(am = a.length - 1) >= 0) { |
2369 |
< |
long j = ((am & s) << ASHIFT) + ABASE; |
2370 |
< |
U.putOrderedObject(a, j, task); |
2371 |
< |
U.putOrderedInt(q, QTOP, s + 1); |
2372 |
< |
submitted = true; |
2366 |
> |
if ((a != null && a.length > s + 1 - q.base) || |
2367 |
> |
(a = q.growArray()) != null) { |
2368 |
> |
int al = a.length, j = (al - 1) & s; |
2369 |
> |
if (al > 0) { |
2370 |
> |
setAt(a, j, task); |
2371 |
> |
U.putOrderedInt(q, QTOP, s + 1); |
2372 |
> |
submitted = true; |
2373 |
> |
} |
2374 |
|
} |
2375 |
|
} finally { |
2376 |
|
U.compareAndSwapInt(q, QLOCK, 1, 0); |
2412 |
|
WorkQueue[] ws; WorkQueue q; int m; |
2413 |
|
int r = ThreadLocalRandom.getProbe(); |
2414 |
|
int rs = runState; |
2415 |
< |
if ((ws = workQueues) != null && (m = (ws.length - 1)) >= 0 && |
2415 |
> |
if ((ws = workQueues) != null && (m = (ws.length - 1)) > 0 && |
2416 |
|
(q = ws[m & r & SQMASK]) != null && r != 0 && rs > 0 && |
2417 |
|
U.compareAndSwapInt(q, QLOCK, 0, 1)) { |
2418 |
|
ForkJoinTask<?>[] a; |
2419 |
|
if ((a = q.array) != null) { |
2420 |
< |
int b = q.base, am = a.length - 1, s, n; |
2421 |
< |
long j = ((am & (s = q.top)) << ASHIFT) + ABASE; |
2422 |
< |
if (am > (n = s - b) && am >= 0) { |
2423 |
< |
U.putOrderedObject(a, j, task); |
2424 |
< |
U.putOrderedInt(q, QTOP, s + 1); |
2425 |
< |
U.putOrderedInt(q, QLOCK, 0); |
2426 |
< |
if (n <= 1) |
2427 |
< |
signalWork(ws, q); |
2428 |
< |
return; |
2420 |
> |
int b = q.base, al = a.length, s = q.top; |
2421 |
> |
if (al > 0) { |
2422 |
> |
int am = al - 1, j = am & s, n; |
2423 |
> |
if ((n = s - b) < am) { |
2424 |
> |
setAt(a, j, task); |
2425 |
> |
U.putOrderedInt(q, QTOP, s + 1); |
2426 |
> |
U.putOrderedInt(q, QLOCK, 0); |
2427 |
> |
if (n <= 1) |
2428 |
> |
signalWork(ws, q); |
2429 |
> |
return; |
2430 |
> |
} |
2431 |
|
} |
2432 |
|
} |
2433 |
|
U.compareAndSwapInt(q, QLOCK, 1, 0); |
2443 |
|
int r = ThreadLocalRandom.getProbe(); |
2444 |
|
WorkQueue[] ws; int m; |
2445 |
|
return (p != null && (ws = p.workQueues) != null && |
2446 |
< |
(m = ws.length - 1) >= 0) ? |
2446 |
> |
(m = ws.length - 1) > 0) ? |
2447 |
|
ws[m & r & SQMASK] : null; |
2448 |
|
} |
2449 |
|
|
2455 |
|
final boolean tryExternalUnpush(ForkJoinTask<?> task) { |
2456 |
|
WorkQueue[] ws; WorkQueue w; ForkJoinTask<?>[] a; int m; |
2457 |
|
int r = ThreadLocalRandom.getProbe(); |
2458 |
< |
if ((ws = workQueues) != null && (m = ws.length - 1) >= 0 && |
2458 |
> |
if ((ws = workQueues) != null && (m = ws.length - 1) > 0 && |
2459 |
|
(w = ws[m & r & SQMASK]) != null && |
2460 |
|
(a = w.array) != null) { |
2461 |
< |
int b = w.base, am = a.length - 1, s = w.top; |
2462 |
< |
long j = ((am & (s - 1)) << ASHIFT) + ABASE; |
2463 |
< |
if (s != b && am >= 0 && U.compareAndSwapInt(w, QLOCK, 0, 1)) { |
2464 |
< |
if (w.top == s && w.array == a && |
2465 |
< |
U.getObject(a, j) == task && |
2441 |
< |
U.compareAndSwapObject(a, j, task, null)) { |
2461 |
> |
int b = w.base, al = a.length, s = w.top; |
2462 |
> |
if (s != b && al > 0 && |
2463 |
> |
U.compareAndSwapInt(w, QLOCK, 0, 1)) { |
2464 |
> |
int i = (al - 1) & (s - 1); |
2465 |
> |
if (w.top == s && w.array == a && casAt(a, i, task, null)) { |
2466 |
|
U.putOrderedInt(w, QTOP, s - 1); |
2467 |
|
U.putOrderedInt(w, QLOCK, 0); |
2468 |
|
return true; |
3185 |
|
int r = 0, m; |
3186 |
|
boolean found = true; |
3187 |
|
while (!isQuiescent() && (ws = workQueues) != null && |
3188 |
< |
(m = ws.length - 1) >= 0) { |
3188 |
> |
(m = ws.length - 1) > 0) { |
3189 |
|
if (!found) { |
3190 |
|
if ((System.nanoTime() - startTime) > nanos) |
3191 |
|
return false; |