931 |
|
* interior remove while in detached mode. |
932 |
|
*/ |
933 |
|
private class Itr implements Iterator<E> { |
934 |
< |
/** Index to look for new nextItem; -1 at end */ |
934 |
> |
/** Index to look for new nextItem; NONE at end */ |
935 |
|
private int cursor; |
936 |
|
|
937 |
|
/** Element to be returned by next call to next(); null if none */ |
938 |
|
private E nextItem; |
939 |
|
|
940 |
< |
/** Index of nextItem; -1 if none, -2 if removed elsewhere */ |
940 |
> |
/** Index of nextItem; NONE if none, REMOVED if removed elsewhere */ |
941 |
|
private int nextIndex; |
942 |
|
|
943 |
|
/** Last element returned; null if none or not detached. */ |
944 |
|
private E lastItem; |
945 |
|
|
946 |
< |
/** Index of lastItem, -1 if none, -2 if removed elsewhere */ |
946 |
> |
/** Index of lastItem, NONE if none, REMOVED if removed elsewhere */ |
947 |
|
private int lastRet; |
948 |
|
|
949 |
< |
/** Previous value of takeIndex; -1 if detached */ |
949 |
> |
/** Previous value of takeIndex, or DETACHED when detached */ |
950 |
|
private int prevTakeIndex; |
951 |
|
|
952 |
|
/** Previous value of iters.cycles */ |
953 |
|
private int prevCycles; |
954 |
|
|
955 |
+ |
/** Special index value indicating "not available" or "undefined" */ |
956 |
+ |
private static final int NONE = -1; |
957 |
+ |
|
958 |
+ |
/** |
959 |
+ |
* Special index value indicating "removed elsewhere", that is, |
960 |
+ |
* removed by some operation other than a call to this.remove(). |
961 |
+ |
*/ |
962 |
+ |
private static final int REMOVED = -2; |
963 |
+ |
|
964 |
+ |
/** Special value for prevTakeIndex indicating "detached mode" */ |
965 |
+ |
private static final int DETACHED = -3; |
966 |
+ |
|
967 |
|
Itr() { |
968 |
|
assert lock.getHoldCount() == 0; |
969 |
< |
lastRet = -1; |
969 |
> |
lastRet = NONE; |
970 |
|
final ReentrantLock lock = ArrayBlockingQueue.this.lock; |
971 |
|
lock.lock(); |
972 |
|
try { |
973 |
|
if (count == 0) { |
974 |
|
assert itrs == null; |
975 |
< |
cursor = -1; |
976 |
< |
nextIndex = -1; |
977 |
< |
prevTakeIndex = -1; |
975 |
> |
cursor = NONE; |
976 |
> |
nextIndex = NONE; |
977 |
> |
prevTakeIndex = DETACHED; |
978 |
|
} else { |
979 |
|
final int takeIndex = ArrayBlockingQueue.this.takeIndex; |
980 |
|
prevTakeIndex = takeIndex; |
1007 |
|
assert lock.getHoldCount() == 1; |
1008 |
|
index = inc(index); |
1009 |
|
if (index == putIndex) |
1010 |
< |
index = -1; |
1010 |
> |
index = NONE; |
1011 |
|
return index; |
1012 |
|
} |
1013 |
|
|
1049 |
|
|
1050 |
|
// Check indices for invalidation |
1051 |
|
if (invalidated(lastRet, prevTakeIndex, dequeues, len)) |
1052 |
< |
lastRet = -2; |
1052 |
> |
lastRet = REMOVED; |
1053 |
|
if (invalidated(nextIndex, prevTakeIndex, dequeues, len)) |
1054 |
< |
nextIndex = -2; |
1054 |
> |
nextIndex = REMOVED; |
1055 |
|
if (invalidated(cursor, prevTakeIndex, dequeues, len)) |
1056 |
|
cursor = takeIndex; |
1057 |
|
|
1074 |
|
private void detach() { |
1075 |
|
// Switch to detached mode |
1076 |
|
assert lock.getHoldCount() == 1; |
1077 |
< |
assert cursor == -1; |
1077 |
> |
assert cursor == NONE; |
1078 |
|
assert nextIndex < 0; |
1079 |
|
assert lastRet < 0 || nextItem == null; |
1080 |
|
assert lastRet < 0 ^ lastItem != null; |
1081 |
|
if (prevTakeIndex >= 0) { |
1082 |
|
assert itrs != null; |
1083 |
< |
prevTakeIndex = -1; |
1083 |
> |
prevTakeIndex = DETACHED; |
1084 |
|
// try to unlink from itrs (but not too hard) |
1085 |
|
itrs.doSomeSweeping(true); |
1086 |
|
} |
1104 |
|
final ReentrantLock lock = ArrayBlockingQueue.this.lock; |
1105 |
|
lock.lock(); |
1106 |
|
try { |
1107 |
< |
assert cursor == -1; |
1108 |
< |
assert nextIndex == -1; |
1107 |
> |
assert cursor == NONE; |
1108 |
> |
assert nextIndex == NONE; |
1109 |
|
if (!isDetached()) { |
1110 |
|
assert itrs != null; |
1111 |
|
assert lastRet >= 0; |
1135 |
|
assert itrs != null; |
1136 |
|
incorporateDequeues(); |
1137 |
|
} |
1138 |
< |
assert nextIndex != -1; |
1138 |
> |
assert nextIndex != NONE; |
1139 |
|
assert lastItem == null; |
1140 |
|
lastRet = nextIndex; |
1141 |
|
final int cursor = this.cursor; |
1144 |
|
assert nextItem != null; |
1145 |
|
this.cursor = incCursor(cursor); |
1146 |
|
} else { |
1147 |
< |
nextIndex = -1; |
1147 |
> |
nextIndex = NONE; |
1148 |
|
nextItem = null; |
1149 |
|
} |
1150 |
|
} finally { |
1170 |
|
if (lastRet >= 0) |
1171 |
|
removeAt(lastRet); |
1172 |
|
} |
1173 |
< |
} else if (lastRet == -1) |
1173 |
> |
} else if (lastRet == NONE) |
1174 |
|
throw new IllegalStateException(); |
1175 |
< |
// else lastRet == -2 and the last returned element was |
1175 |
> |
// else lastRet == REMOVED and the last returned element was |
1176 |
|
// previously asynchronously removed via an operation other |
1177 |
|
// than this.remove(), so nothing to do. |
1178 |
|
|
1179 |
< |
lastRet = -1; |
1179 |
> |
lastRet = NONE; |
1180 |
|
if (cursor < 0 && nextIndex < 0) |
1181 |
|
detach(); |
1182 |
|
} finally { |
1183 |
|
lock.unlock(); |
1184 |
< |
assert lastRet == -1; |
1184 |
> |
assert lastRet == NONE; |
1185 |
|
assert lastItem == null; |
1186 |
|
} |
1187 |
|
} |
1194 |
|
*/ |
1195 |
|
void shutdown() { |
1196 |
|
assert lock.getHoldCount() == 1; |
1197 |
< |
cursor = -1; |
1197 |
> |
cursor = NONE; |
1198 |
|
if (nextIndex >= 0) |
1199 |
< |
nextIndex = -2; |
1199 |
> |
nextIndex = REMOVED; |
1200 |
|
if (lastRet >= 0) { |
1201 |
< |
lastRet = -2; |
1201 |
> |
lastRet = REMOVED; |
1202 |
|
lastItem = null; |
1203 |
|
} |
1204 |
< |
prevTakeIndex = -1; |
1204 |
> |
prevTakeIndex = DETACHED; |
1205 |
|
// Don't set nextItem to null because we must continue to be |
1206 |
|
// able to return it on next(). |
1207 |
|
// |
1241 |
|
int x = distance(cursor, prevTakeIndex, len); |
1242 |
|
if (x == removedDistance) { |
1243 |
|
if (cursor == putIndex) |
1244 |
< |
this.cursor = cursor = -1; |
1244 |
> |
this.cursor = cursor = NONE; |
1245 |
|
} |
1246 |
|
else if (x > removedDistance) { |
1247 |
|
assert cursor != prevTakeIndex; |
1252 |
|
if (lastRet >= 0) { |
1253 |
|
int x = distance(lastRet, prevTakeIndex, len); |
1254 |
|
if (x == removedDistance) |
1255 |
< |
this.lastRet = lastRet = -2; |
1255 |
> |
this.lastRet = lastRet = REMOVED; |
1256 |
|
else if (x > removedDistance) |
1257 |
|
this.lastRet = lastRet = dec(lastRet); |
1258 |
|
} |
1260 |
|
if (nextIndex >= 0) { |
1261 |
|
int x = distance(nextIndex, prevTakeIndex, len); |
1262 |
|
if (x == removedDistance) |
1263 |
< |
this.nextIndex = nextIndex = -2; |
1263 |
> |
this.nextIndex = nextIndex = REMOVED; |
1264 |
|
else if (x > removedDistance) |
1265 |
|
this.nextIndex = nextIndex = dec(nextIndex); |
1266 |
|
} |
1267 |
|
else if (cursor < 0 && nextIndex < 0 && lastRet < 0) { |
1268 |
< |
this.prevTakeIndex = -1; |
1268 |
> |
this.prevTakeIndex = DETACHED; |
1269 |
|
return true; |
1270 |
|
} |
1271 |
|
return false; |