138 |
|
/** |
139 |
|
* Lock used for all public operations. |
140 |
|
*/ |
141 |
< |
private final ReentrantLock lock; |
141 |
> |
private final ReentrantLock lock = new ReentrantLock(); |
142 |
|
|
143 |
|
/** |
144 |
|
* Condition for blocking when empty. |
145 |
|
*/ |
146 |
< |
private final Condition notEmpty; |
146 |
> |
private final Condition notEmpty = lock.newCondition(); |
147 |
|
|
148 |
|
/** |
149 |
|
* Spinlock for allocation, acquired via CAS. |
195 |
|
Comparator<? super E> comparator) { |
196 |
|
if (initialCapacity < 1) |
197 |
|
throw new IllegalArgumentException(); |
198 |
– |
this.lock = new ReentrantLock(); |
199 |
– |
this.notEmpty = lock.newCondition(); |
198 |
|
this.comparator = comparator; |
199 |
< |
this.queue = new Object[initialCapacity]; |
199 |
> |
this.queue = new Object[Math.max(1, initialCapacity)]; |
200 |
|
} |
201 |
|
|
202 |
|
/** |
216 |
|
* of its elements are null |
217 |
|
*/ |
218 |
|
public PriorityBlockingQueue(Collection<? extends E> c) { |
221 |
– |
this.lock = new ReentrantLock(); |
222 |
– |
this.notEmpty = lock.newCondition(); |
219 |
|
boolean heapify = true; // true if not known to be in heap order |
220 |
|
boolean screen = true; // true if must screen for nulls |
221 |
|
if (c instanceof SortedSet<?>) { |
241 |
|
if (e == null) |
242 |
|
throw new NullPointerException(); |
243 |
|
} |
244 |
< |
this.queue = es; |
244 |
> |
this.queue = ensureNonEmpty(es); |
245 |
|
this.size = n; |
246 |
|
if (heapify) |
247 |
|
heapify(); |
248 |
|
} |
249 |
|
|
250 |
+ |
/** Ensures that queue[0] exists, helping peek() and poll(). */ |
251 |
+ |
private static Object[] ensureNonEmpty(Object[] es) { |
252 |
+ |
return (es.length > 0) ? es : new Object[1]; |
253 |
+ |
} |
254 |
+ |
|
255 |
|
/** |
256 |
|
* Tries to grow array to accommodate at least one more element |
257 |
|
* (but normally expand by about 50%), giving up (allowing retry) |
296 |
|
*/ |
297 |
|
private E dequeue() { |
298 |
|
// assert lock.isHeldByCurrentThread(); |
299 |
< |
int n = size - 1; |
300 |
< |
if (n < 0) |
301 |
< |
return null; |
302 |
< |
else { |
303 |
< |
final Object[] es = queue; |
304 |
< |
E result = (E) es[0]; |
304 |
< |
E x = (E) es[n]; |
299 |
> |
final Object[] es; |
300 |
> |
final E result; |
301 |
> |
|
302 |
> |
if ((result = (E) ((es = queue)[0])) != null) { |
303 |
> |
final int n; |
304 |
> |
final E x = (E) es[(n = --size)]; |
305 |
|
es[n] = null; |
306 |
|
if (n > 0) { |
307 |
< |
Comparator<? super E> cmp = comparator; |
308 |
< |
if (cmp == null) |
307 |
> |
final Comparator<? super E> cmp; |
308 |
> |
if ((cmp = comparator) == null) |
309 |
|
siftDownComparable(0, x, es, n); |
310 |
|
else |
311 |
|
siftDownUsingComparator(0, x, es, n, cmp); |
312 |
|
} |
313 |
– |
size = n; |
314 |
– |
return result; |
313 |
|
} |
314 |
+ |
return result; |
315 |
|
} |
316 |
|
|
317 |
|
/** |
408 |
|
private void heapify() { |
409 |
|
final Object[] es = queue; |
410 |
|
int n = size, i = (n >>> 1) - 1; |
411 |
< |
Comparator<? super E> cmp = comparator; |
412 |
< |
if (cmp == null) |
411 |
> |
final Comparator<? super E> cmp; |
412 |
> |
if ((cmp = comparator) == null) |
413 |
|
for (; i >= 0; i--) |
414 |
|
siftDownComparable(i, (E) es[i], es, n); |
415 |
|
else |
452 |
|
while ((n = size) >= (cap = (array = queue).length)) |
453 |
|
tryGrow(array, cap); |
454 |
|
try { |
455 |
< |
Comparator<? super E> cmp = comparator; |
456 |
< |
if (cmp == null) |
455 |
> |
final Comparator<? super E> cmp; |
456 |
> |
if ((cmp = comparator) == null) |
457 |
|
siftUpComparable(n, e, array); |
458 |
|
else |
459 |
|
siftUpUsingComparator(n, e, array, cmp); |
539 |
|
final ReentrantLock lock = this.lock; |
540 |
|
lock.lock(); |
541 |
|
try { |
542 |
< |
return (size == 0) ? null : (E) queue[0]; |
542 |
> |
return (E) queue[0]; |
543 |
|
} finally { |
544 |
|
lock.unlock(); |
545 |
|
} |
592 |
|
*/ |
593 |
|
private void removeAt(int i) { |
594 |
|
final Object[] es = queue; |
595 |
< |
int n = size - 1; |
595 |
> |
final int n = size - 1; |
596 |
|
if (n == i) // removed last element |
597 |
|
es[i] = null; |
598 |
|
else { |
599 |
|
E moved = (E) es[n]; |
600 |
|
es[n] = null; |
601 |
< |
Comparator<? super E> cmp = comparator; |
602 |
< |
if (cmp == null) |
601 |
> |
final Comparator<? super E> cmp; |
602 |
> |
if ((cmp = comparator) == null) |
603 |
|
siftDownComparable(i, moved, es, n); |
604 |
|
else |
605 |
|
siftDownUsingComparator(i, moved, es, n, cmp); |
891 |
|
s.defaultReadObject(); |
892 |
|
int sz = q.size(); |
893 |
|
SharedSecrets.getJavaObjectInputStreamAccess().checkArray(s, Object[].class, sz); |
894 |
< |
this.queue = new Object[sz]; |
894 |
> |
this.queue = new Object[Math.max(1, sz)]; |
895 |
|
comparator = q.comparator(); |
896 |
|
addAll(q); |
897 |
|
} finally { |