832 |
|
*/ |
833 |
|
final void push(ForkJoinTask<?> task) { |
834 |
|
ForkJoinTask<?>[] a; ForkJoinPool p; |
835 |
< |
int b = base, s = top, n; |
836 |
< |
if ((a = array) != null) { // ignore if queue removed |
837 |
< |
int m = a.length - 1; // fenced write for task visibility |
838 |
< |
U.putOrderedObject(a, ((m & s) << ASHIFT) + ABASE, task); |
839 |
< |
U.putOrderedInt(this, QTOP, s + 1); |
840 |
< |
if ((n = s - b) <= 1) { |
841 |
< |
if ((p = pool) != null) |
842 |
< |
p.signalWork(p.workQueues, this); |
835 |
> |
if ((a = array) != null) { // ignore if no queue |
836 |
> |
int b = base, m = a.length - 1, s = top, n; |
837 |
> |
long j = ((m & s) << ASHIFT) + ABASE; |
838 |
> |
if (m >= 0) { |
839 |
> |
U.putOrderedObject(a, j, task); |
840 |
> |
U.putOrderedInt(this, QTOP, s + 1); |
841 |
> |
if ((n = s - b) <= 1) { |
842 |
> |
if ((p = pool) != null) |
843 |
> |
p.signalWork(p.workQueues, this); |
844 |
> |
} |
845 |
> |
else if (n >= m) |
846 |
> |
growArray(); |
847 |
|
} |
844 |
– |
else if (n >= m) |
845 |
– |
growArray(); |
848 |
|
} |
849 |
|
} |
850 |
|
|
856 |
|
final ForkJoinTask<?>[] growArray() { |
857 |
|
ForkJoinTask<?>[] oldA = array; |
858 |
|
int size = oldA != null ? oldA.length << 1 : INITIAL_QUEUE_CAPACITY; |
859 |
< |
if (size > MAXIMUM_QUEUE_CAPACITY) |
859 |
> |
if (size < 0 || size > MAXIMUM_QUEUE_CAPACITY) |
860 |
|
throw new RejectedExecutionException("Queue capacity exceeded"); |
861 |
|
int oldMask, t, b; |
862 |
|
ForkJoinTask<?>[] a = array = new ForkJoinTask<?>[size]; |
865 |
|
int mask = size - 1; |
866 |
|
do { // emulate poll from old array, push to new array |
867 |
|
ForkJoinTask<?> x; |
868 |
< |
int oldj = ((b & oldMask) << ASHIFT) + ABASE; |
869 |
< |
int j = ((b & mask) << ASHIFT) + ABASE; |
868 |
> |
long oldj = ((b & oldMask) << ASHIFT) + ABASE; |
869 |
> |
long j = ((b & mask) << ASHIFT) + ABASE; |
870 |
|
x = (ForkJoinTask<?>)U.getObjectVolatile(oldA, oldj); |
871 |
|
if (x != null && |
872 |
|
U.compareAndSwapObject(oldA, oldj, x, null)) |
904 |
|
final ForkJoinTask<?> pollAt(int b) { |
905 |
|
ForkJoinTask<?> t; ForkJoinTask<?>[] a; |
906 |
|
if ((a = array) != null) { |
907 |
< |
int j = (((a.length - 1) & b) << ASHIFT) + ABASE; |
908 |
< |
if ((t = (ForkJoinTask<?>)U.getObjectVolatile(a, j)) != null && |
907 |
> |
int m = a.length - 1; |
908 |
> |
long j = ((m & b) << ASHIFT) + ABASE; |
909 |
> |
if (m >= 0 && |
910 |
> |
(t = (ForkJoinTask<?>)U.getObjectVolatile(a, j)) != null && |
911 |
|
base == b && U.compareAndSwapObject(a, j, t, null)) { |
912 |
|
base = b + 1; |
913 |
|
return t; |
922 |
|
final ForkJoinTask<?> poll() { |
923 |
|
ForkJoinTask<?>[] a; int b; ForkJoinTask<?> t; |
924 |
|
while ((b = base) - top < 0 && (a = array) != null) { |
925 |
< |
int j = (((a.length - 1) & b) << ASHIFT) + ABASE; |
925 |
> |
int m = a.length - 1; |
926 |
> |
long j = ((m & b) << ASHIFT) + ABASE; |
927 |
> |
if (m < 0) |
928 |
> |
break; |
929 |
|
t = (ForkJoinTask<?>)U.getObjectVolatile(a, j); |
930 |
|
if (base == b) { |
931 |
|
if (t != null) { |
956 |
|
if (a == null || (m = a.length - 1) < 0) |
957 |
|
return null; |
958 |
|
int i = (config & FIFO_QUEUE) == 0 ? top - 1 : base; |
959 |
< |
int j = ((i & m) << ASHIFT) + ABASE; |
959 |
> |
long j = ((i & m) << ASHIFT) + ABASE; |
960 |
|
return (ForkJoinTask<?>)U.getObjectVolatile(a, j); |
961 |
|
} |
962 |
|
|
965 |
|
* (A shared version is available only via FJP.tryExternalUnpush) |
966 |
|
*/ |
967 |
|
final boolean tryUnpush(ForkJoinTask<?> t) { |
968 |
< |
ForkJoinTask<?>[] a; int s; |
969 |
< |
if ((a = array) != null && (s = top) != base && |
970 |
< |
U.compareAndSwapObject |
971 |
< |
(a, (((a.length - 1) & --s) << ASHIFT) + ABASE, t, null)) { |
972 |
< |
U.putOrderedInt(this, QTOP, s); |
973 |
< |
return true; |
968 |
> |
ForkJoinTask<?>[] a; |
969 |
> |
if ((a = array) != null) { |
970 |
> |
int b = base, m = a.length - 1, s = top; |
971 |
> |
long j = ((m & (s - 1)) << ASHIFT) + ABASE; |
972 |
> |
if (s != b && m >= 0 && |
973 |
> |
U.compareAndSwapObject(a, j, t, null)) { |
974 |
> |
U.putOrderedInt(this, QTOP, s - 1); |
975 |
> |
return true; |
976 |
> |
} |
977 |
|
} |
978 |
|
return false; |
979 |
|
} |
1017 |
|
(m = a.length - 1) >= 0) { |
1018 |
|
if ((config & FIFO_QUEUE) == 0) { |
1019 |
|
for (ForkJoinTask<?> t;;) { |
1020 |
+ |
long j = ((m & s) << ASHIFT) + ABASE; |
1021 |
|
if ((t = (ForkJoinTask<?>)U.getAndSetObject |
1022 |
< |
(a, ((m & s) << ASHIFT) + ABASE, null)) == null) |
1022 |
> |
(a, j, null)) == null) |
1023 |
|
break; |
1024 |
|
U.putOrderedInt(this, QTOP, s); |
1025 |
|
t.doExec(); |
1114 |
|
final CountedCompleter<?> popCC(CountedCompleter<?> task, int mode) { |
1115 |
|
int s; ForkJoinTask<?>[] a; Object o; |
1116 |
|
if (base - (s = top) < 0 && (a = array) != null) { |
1117 |
< |
long j = (((a.length - 1) & (s - 1)) << ASHIFT) + ABASE; |
1118 |
< |
if ((o = U.getObjectVolatile(a, j)) != null && |
1117 |
> |
int m = a.length - 1; |
1118 |
> |
long j = ((m & (s - 1)) << ASHIFT) + ABASE; |
1119 |
> |
if (m >= 0 && (o = U.getObjectVolatile(a, j)) != null && |
1120 |
|
(o instanceof CountedCompleter)) { |
1121 |
|
CountedCompleter<?> t = (CountedCompleter<?>)o; |
1122 |
|
for (CountedCompleter<?> r = t;;) { |
1161 |
|
if ((b = base) - top >= 0 || (a = array) == null) |
1162 |
|
h = b | Integer.MIN_VALUE; // to sense movement on re-poll |
1163 |
|
else { |
1164 |
< |
long j = (((a.length - 1) & b) << ASHIFT) + ABASE; |
1165 |
< |
if ((o = U.getObjectVolatile(a, j)) == null) |
1164 |
> |
int m = a.length - 1; |
1165 |
> |
long j = ((m & b) << ASHIFT) + ABASE; |
1166 |
> |
if (m < 0 || (o = U.getObjectVolatile(a, j)) == null) |
1167 |
|
h = 2; // retryable |
1168 |
|
else if (!(o instanceof CountedCompleter)) |
1169 |
|
h = -1; // unmatchable |
1704 |
|
int ss = w.scanState; // initially non-negative |
1705 |
|
for (int origin = r & m, k = origin, oldSum = 0, checkSum = 0;;) { |
1706 |
|
WorkQueue q; ForkJoinTask<?>[] a; ForkJoinTask<?> t; |
1707 |
< |
int b, n; long c; |
1707 |
> |
int b, am, n; long c; |
1708 |
|
if ((q = ws[k]) != null) { |
1709 |
< |
if ((n = (b = q.base) - q.top) < 0 && |
1710 |
< |
(a = q.array) != null) { // non-empty |
1711 |
< |
long i = (((a.length - 1) & b) << ASHIFT) + ABASE; |
1712 |
< |
if ((t = ((ForkJoinTask<?>) |
1709 |
> |
if ((n = (b = q.base) - q.top) < 0 && // non-empty |
1710 |
> |
(a = q.array) != null) { |
1711 |
> |
long i = (((am = a.length - 1) & b) << ASHIFT) + ABASE; |
1712 |
> |
if (am >= 0 && |
1713 |
> |
(t = ((ForkJoinTask<?>) |
1714 |
|
U.getObjectVolatile(a, i))) != null && |
1715 |
|
q.base == b) { |
1716 |
|
if (ss >= 0) { |
1918 |
|
} |
1919 |
|
} |
1920 |
|
for (;;) { // help v or descend |
1921 |
< |
ForkJoinTask<?>[] a; int b; |
1921 |
> |
ForkJoinTask<?>[] a; int b, am; |
1922 |
|
checkSum += (b = v.base); |
1923 |
|
ForkJoinTask<?> next = v.currentJoin; |
1924 |
|
if (subtask.status < 0 || j.currentJoin != subtask || |
1925 |
|
v.currentSteal != subtask) // stale |
1926 |
|
break descent; |
1927 |
< |
if (b - v.top >= 0 || (a = v.array) == null) { |
1927 |
> |
if (b - v.top >= 0 || (a = v.array) == null || |
1928 |
> |
(am = a.length - 1) < 0) { |
1929 |
|
if ((subtask = next) == null) |
1930 |
|
break descent; |
1931 |
|
j = v; |
1932 |
|
break; |
1933 |
|
} |
1934 |
< |
int i = (((a.length - 1) & b) << ASHIFT) + ABASE; |
1934 |
> |
long i = ((am & b) << ASHIFT) + ABASE; |
1935 |
|
ForkJoinTask<?> t = ((ForkJoinTask<?>) |
1936 |
|
U.getObjectVolatile(a, i)); |
1937 |
|
if (v.base == b) { |
2338 |
|
else if ((q = ws[k = r & m & SQMASK]) != null) { |
2339 |
|
if (q.qlock == 0 && U.compareAndSwapInt(q, QLOCK, 0, 1)) { |
2340 |
|
ForkJoinTask<?>[] a = q.array; |
2341 |
< |
int s = q.top; |
2341 |
> |
int s = q.top, am; |
2342 |
|
boolean submitted = false; // initial submission or resizing |
2343 |
|
try { // locked version of push |
2344 |
< |
if ((a != null && a.length > s + 1 - q.base) || |
2345 |
< |
(a = q.growArray()) != null) { |
2346 |
< |
int j = (((a.length - 1) & s) << ASHIFT) + ABASE; |
2344 |
> |
if (((a != null && a.length > s + 1 - q.base) || |
2345 |
> |
(a = q.growArray()) != null) && |
2346 |
> |
(am = a.length - 1) >= 0) { |
2347 |
> |
long j = ((am & s) << ASHIFT) + ABASE; |
2348 |
|
U.putOrderedObject(a, j, task); |
2349 |
|
U.putOrderedInt(q, QTOP, s + 1); |
2350 |
|
submitted = true; |
2392 |
|
if ((ws = workQueues) != null && (m = (ws.length - 1)) >= 0 && |
2393 |
|
(q = ws[m & r & SQMASK]) != null && r != 0 && rs > 0 && |
2394 |
|
U.compareAndSwapInt(q, QLOCK, 0, 1)) { |
2395 |
< |
ForkJoinTask<?>[] a; int am, n, s; |
2396 |
< |
if ((a = q.array) != null && |
2397 |
< |
(am = a.length - 1) > (n = (s = q.top) - q.base)) { |
2398 |
< |
int j = ((am & s) << ASHIFT) + ABASE; |
2399 |
< |
U.putOrderedObject(a, j, task); |
2400 |
< |
U.putOrderedInt(q, QTOP, s + 1); |
2401 |
< |
U.putOrderedInt(q, QLOCK, 0); |
2402 |
< |
if (n <= 1) |
2403 |
< |
signalWork(ws, q); |
2404 |
< |
return; |
2395 |
> |
ForkJoinTask<?>[] a; |
2396 |
> |
if ((a = q.array) != null) { |
2397 |
> |
int b = q.base, am = a.length - 1, s, n; |
2398 |
> |
long j = ((am & (s = q.top)) << ASHIFT) + ABASE; |
2399 |
> |
if (am > (n = s - b) && am >= 0) { |
2400 |
> |
U.putOrderedObject(a, j, task); |
2401 |
> |
U.putOrderedInt(q, QTOP, s + 1); |
2402 |
> |
U.putOrderedInt(q, QLOCK, 0); |
2403 |
> |
if (n <= 1) |
2404 |
> |
signalWork(ws, q); |
2405 |
> |
return; |
2406 |
> |
} |
2407 |
|
} |
2408 |
|
U.compareAndSwapInt(q, QLOCK, 1, 0); |
2409 |
|
} |
2428 |
|
* adjusts top. Each check can fail but rarely does. |
2429 |
|
*/ |
2430 |
|
final boolean tryExternalUnpush(ForkJoinTask<?> task) { |
2431 |
< |
WorkQueue[] ws; WorkQueue w; ForkJoinTask<?>[] a; int m, s; |
2431 |
> |
WorkQueue[] ws; WorkQueue w; ForkJoinTask<?>[] a; int m; |
2432 |
|
int r = ThreadLocalRandom.getProbe(); |
2433 |
|
if ((ws = workQueues) != null && (m = ws.length - 1) >= 0 && |
2434 |
|
(w = ws[m & r & SQMASK]) != null && |
2435 |
< |
(a = w.array) != null && (s = w.top) != w.base) { |
2436 |
< |
long j = (((a.length - 1) & (s - 1)) << ASHIFT) + ABASE; |
2437 |
< |
if (U.compareAndSwapInt(w, QLOCK, 0, 1)) { |
2435 |
> |
(a = w.array) != null) { |
2436 |
> |
int b = w.base, am = a.length - 1, s = w.top; |
2437 |
> |
long j = ((am & (s - 1)) << ASHIFT) + ABASE; |
2438 |
> |
if (s != b && am >= 0 && U.compareAndSwapInt(w, QLOCK, 0, 1)) { |
2439 |
|
if (w.top == s && w.array == a && |
2440 |
|
U.getObject(a, j) == task && |
2441 |
|
U.compareAndSwapObject(a, j, task, null)) { |