You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

InstrumentationTarget.java 24KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761
  1. package test.javassist.convert;
  2. import java.util.AbstractQueue;
  3. import java.util.Collection;
  4. import java.util.Iterator;
  5. import java.util.NoSuchElementException;
  6. import java.util.concurrent.BlockingQueue;
  7. import java.util.concurrent.TimeUnit;
  8. import java.util.concurrent.locks.Condition;
  9. import java.util.concurrent.locks.ReentrantLock;
  10. /**
  11. * A clone of java.util.concurrent.ArrayBlockingQueue as target for testing
  12. */
  13. public class InstrumentationTarget<E> extends AbstractQueue<E>
  14. implements BlockingQueue<E>, java.io.Serializable {
  15. /**
  16. * Serialization ID. This class relies on default serialization
  17. * even for the items array, which is default-serialized, even if
  18. * it is empty. Otherwise it could not be declared final, which is
  19. * necessary here.
  20. */
  21. private static final long serialVersionUID = -817911632652898426L;
  22. /**
  23. * The queued items
  24. */
  25. final Object[] items;
  26. /**
  27. * items index for next take, poll, peek or remove
  28. */
  29. int takeIndex;
  30. /**
  31. * items index for next put, offer, or add
  32. */
  33. int putIndex;
  34. /**
  35. * Number of elements in the queue
  36. */
  37. int count;
  38. /*
  39. * Concurrency control uses the classic two-condition algorithm
  40. * found in any textbook.
  41. */
  42. /**
  43. * Main lock guarding all access
  44. */
  45. final ReentrantLock lock;
  46. /**
  47. * Condition for waiting takes
  48. */
  49. private final Condition notEmpty;
  50. /**
  51. * Condition for waiting puts
  52. */
  53. private final Condition notFull;
  54. // Internal helper methods
  55. /**
  56. * Circularly increment i.
  57. */
  58. final int inc(int i) {
  59. return (++i == items.length) ? 0 : i;
  60. }
  61. /**
  62. * Circularly decrement i.
  63. */
  64. final int dec(int i) {
  65. return ((i == 0) ? items.length : i) - 1;
  66. }
  67. @SuppressWarnings("unchecked")
  68. static <E> E cast(Object item) {
  69. return (E) item;
  70. }
  71. /**
  72. * Returns item at index i.
  73. */
  74. final E itemAt(int i) {
  75. return this.<E>cast(items[i]);
  76. }
  77. /**
  78. * Throws NullPointerException if argument is null.
  79. *
  80. * @param v the element
  81. */
  82. private static void checkNotNull(Object v) {
  83. if (v == null)
  84. throw new NullPointerException();
  85. }
  86. /**
  87. * Inserts element at current put position, advances, and signals.
  88. * Call only when holding lock.
  89. */
  90. private void insert(E x) {
  91. items[putIndex] = x;
  92. putIndex = inc(putIndex);
  93. ++count;
  94. notEmpty.signal();
  95. }
  96. /**
  97. * Extracts element at current take position, advances, and signals.
  98. * Call only when holding lock.
  99. */
  100. private E extract() {
  101. final Object[] items = this.items;
  102. E x = this.<E>cast(items[takeIndex]);
  103. items[takeIndex] = null;
  104. takeIndex = inc(takeIndex);
  105. --count;
  106. notFull.signal();
  107. return x;
  108. }
  109. /**
  110. * Deletes item at position i.
  111. * Utility for remove and iterator.remove.
  112. * Call only when holding lock.
  113. */
  114. void removeAt(int i) {
  115. final Object[] items = this.items;
  116. // if removing front item, just advance
  117. if (i == takeIndex) {
  118. items[takeIndex] = null;
  119. takeIndex = inc(takeIndex);
  120. } else {
  121. // slide over all others up through putIndex.
  122. for (; ; ) {
  123. int nexti = inc(i);
  124. if (nexti != putIndex) {
  125. items[i] = items[nexti];
  126. i = nexti;
  127. } else {
  128. items[i] = null;
  129. putIndex = i;
  130. break;
  131. }
  132. }
  133. }
  134. --count;
  135. notFull.signal();
  136. }
  137. /**
  138. * Creates an {@code Target} with the given (fixed)
  139. * capacity and default access policy.
  140. *
  141. * @param capacity the capacity of this queue
  142. * @throws IllegalArgumentException if {@code capacity < 1}
  143. */
  144. public InstrumentationTarget(int capacity) {
  145. this(capacity, false);
  146. }
  147. /**
  148. * Creates an {@code Target} with the given (fixed)
  149. * capacity and the specified access policy.
  150. *
  151. * @param capacity the capacity of this queue
  152. * @param fair if {@code true} then queue accesses for threads blocked
  153. * on insertion or removal, are processed in FIFO order;
  154. * if {@code false} the access order is unspecified.
  155. * @throws IllegalArgumentException if {@code capacity < 1}
  156. */
  157. public InstrumentationTarget(int capacity, boolean fair) {
  158. if (capacity <= 0)
  159. throw new IllegalArgumentException();
  160. this.items = new Object[capacity];
  161. lock = new ReentrantLock(fair);
  162. notEmpty = lock.newCondition();
  163. notFull = lock.newCondition();
  164. }
  165. /**
  166. * Creates an {@code Target} with the given (fixed)
  167. * capacity, the specified access policy and initially containing the
  168. * elements of the given collection,
  169. * added in traversal order of the collection's iterator.
  170. *
  171. * @param capacity the capacity of this queue
  172. * @param fair if {@code true} then queue accesses for threads blocked
  173. * on insertion or removal, are processed in FIFO order;
  174. * if {@code false} the access order is unspecified.
  175. * @param c the collection of elements to initially contain
  176. * @throws IllegalArgumentException if {@code capacity} is less than
  177. * {@code c.size()}, or less than 1.
  178. * @throws NullPointerException if the specified collection or any
  179. * of its elements are null
  180. */
  181. public InstrumentationTarget(int capacity, boolean fair,
  182. Collection<? extends E> c) {
  183. this(capacity, fair);
  184. final ReentrantLock lock = this.lock;
  185. lock.lock(); // Lock only for visibility, not mutual exclusion
  186. try {
  187. int i = 0;
  188. try {
  189. for (E e : c) {
  190. checkNotNull(e);
  191. items[i++] = e;
  192. }
  193. } catch (ArrayIndexOutOfBoundsException ex) {
  194. throw new IllegalArgumentException();
  195. }
  196. count = i;
  197. putIndex = (i == capacity) ? 0 : i;
  198. } finally {
  199. lock.unlock();
  200. }
  201. }
  202. /**
  203. * Inserts the specified element at the tail of this queue if it is
  204. * possible to do so immediately without exceeding the queue's capacity,
  205. * returning {@code true} upon success and throwing an
  206. * {@code IllegalStateException} if this queue is full.
  207. *
  208. * @param e the element to add
  209. * @return {@code true} (as specified by {@link Collection#add})
  210. * @throws IllegalStateException if this queue is full
  211. * @throws NullPointerException if the specified element is null
  212. */
  213. public boolean add(E e) {
  214. return super.add(e);
  215. }
  216. /**
  217. * Inserts the specified element at the tail of this queue if it is
  218. * possible to do so immediately without exceeding the queue's capacity,
  219. * returning {@code true} upon success and {@code false} if this queue
  220. * is full. This method is generally preferable to method {@link #add},
  221. * which can fail to insert an element only by throwing an exception.
  222. *
  223. * @throws NullPointerException if the specified element is null
  224. */
  225. public boolean offer(E e) {
  226. checkNotNull(e);
  227. final ReentrantLock lock = this.lock;
  228. lock.lock();
  229. try {
  230. if (count == items.length)
  231. return false;
  232. else {
  233. insert(e);
  234. return true;
  235. }
  236. } finally {
  237. lock.unlock();
  238. }
  239. }
  240. /**
  241. * Inserts the specified element at the tail of this queue, waiting
  242. * for space to become available if the queue is full.
  243. *
  244. * @throws InterruptedException {@inheritDoc}
  245. * @throws NullPointerException {@inheritDoc}
  246. */
  247. public void put(E e) throws InterruptedException {
  248. checkNotNull(e);
  249. final ReentrantLock lock = this.lock;
  250. lock.lockInterruptibly();
  251. try {
  252. while (count == items.length)
  253. notFull.await();
  254. insert(e);
  255. } finally {
  256. lock.unlock();
  257. }
  258. }
  259. /**
  260. * Inserts the specified element at the tail of this queue, waiting
  261. * up to the specified wait time for space to become available if
  262. * the queue is full.
  263. *
  264. * @throws InterruptedException {@inheritDoc}
  265. * @throws NullPointerException {@inheritDoc}
  266. */
  267. public boolean offer(E e, long timeout, TimeUnit unit)
  268. throws InterruptedException {
  269. checkNotNull(e);
  270. long nanos = unit.toNanos(timeout);
  271. final ReentrantLock lock = this.lock;
  272. lock.lockInterruptibly();
  273. try {
  274. while (count == items.length) {
  275. if (nanos <= 0)
  276. return false;
  277. nanos = notFull.awaitNanos(nanos);
  278. }
  279. insert(e);
  280. return true;
  281. } finally {
  282. lock.unlock();
  283. }
  284. }
  285. public E poll() {
  286. final ReentrantLock lock = this.lock;
  287. lock.lock();
  288. try {
  289. return (count == 0) ? null : extract();
  290. } finally {
  291. lock.unlock();
  292. }
  293. }
  294. public E take() throws InterruptedException {
  295. final ReentrantLock lock = this.lock;
  296. lock.lockInterruptibly();
  297. try {
  298. while (count == 0)
  299. notEmpty.await();
  300. return extract();
  301. } finally {
  302. lock.unlock();
  303. }
  304. }
  305. public E poll(long timeout, TimeUnit unit) throws InterruptedException {
  306. long nanos = unit.toNanos(timeout);
  307. final ReentrantLock lock = this.lock;
  308. lock.lockInterruptibly();
  309. try {
  310. while (count == 0) {
  311. if (nanos <= 0)
  312. return null;
  313. nanos = notEmpty.awaitNanos(nanos);
  314. }
  315. return extract();
  316. } finally {
  317. lock.unlock();
  318. }
  319. }
  320. public E peek() {
  321. final ReentrantLock lock = this.lock;
  322. lock.lock();
  323. try {
  324. return (count == 0) ? null : itemAt(takeIndex);
  325. } finally {
  326. lock.unlock();
  327. }
  328. }
  329. // this doc comment is overridden to remove the reference to collections
  330. // greater in size than Integer.MAX_VALUE
  331. /**
  332. * Returns the number of elements in this queue.
  333. *
  334. * @return the number of elements in this queue
  335. */
  336. public int size() {
  337. final ReentrantLock lock = this.lock;
  338. lock.lock();
  339. try {
  340. return count;
  341. } finally {
  342. lock.unlock();
  343. }
  344. }
  345. // this doc comment is a modified copy of the inherited doc comment,
  346. // without the reference to unlimited queues.
  347. /**
  348. * Returns the number of additional elements that this queue can ideally
  349. * (in the absence of memory or resource constraints) accept without
  350. * blocking. This is always equal to the initial capacity of this queue
  351. * less the current {@code size} of this queue.
  352. *
  353. * <p>Note that you <em>cannot</em> always tell if an attempt to insert
  354. * an element will succeed by inspecting {@code remainingCapacity}
  355. * because it may be the case that another thread is about to
  356. * insert or remove an element.
  357. */
  358. public int remainingCapacity() {
  359. final ReentrantLock lock = this.lock;
  360. lock.lock();
  361. try {
  362. return items.length - count;
  363. } finally {
  364. lock.unlock();
  365. }
  366. }
  367. /**
  368. * Removes a single instance of the specified element from this queue,
  369. * if it is present. More formally, removes an element {@code e} such
  370. * that {@code o.equals(e)}, if this queue contains one or more such
  371. * elements.
  372. * Returns {@code true} if this queue contained the specified element
  373. * (or equivalently, if this queue changed as a result of the call).
  374. *
  375. * <p>Removal of interior elements in circular array based queues
  376. * is an intrinsically slow and disruptive operation, so should
  377. * be undertaken only in exceptional circumstances, ideally
  378. * only when the queue is known not to be accessible by other
  379. * threads.
  380. *
  381. * @param o element to be removed from this queue, if present
  382. * @return {@code true} if this queue changed as a result of the call
  383. */
  384. public boolean remove(Object o) {
  385. if (o == null) return false;
  386. final Object[] items = this.items;
  387. final ReentrantLock lock = this.lock;
  388. lock.lock();
  389. try {
  390. for (int i = takeIndex, k = count; k > 0; i = inc(i), k--) {
  391. if (o.equals(items[i])) {
  392. removeAt(i);
  393. return true;
  394. }
  395. }
  396. return false;
  397. } finally {
  398. lock.unlock();
  399. }
  400. }
  401. /**
  402. * Returns {@code true} if this queue contains the specified element.
  403. * More formally, returns {@code true} if and only if this queue contains
  404. * at least one element {@code e} such that {@code o.equals(e)}.
  405. *
  406. * @param o object to be checked for containment in this queue
  407. * @return {@code true} if this queue contains the specified element
  408. */
  409. public boolean contains(Object o) {
  410. if (o == null) return false;
  411. final Object[] items = this.items;
  412. final ReentrantLock lock = this.lock;
  413. lock.lock();
  414. try {
  415. for (int i = takeIndex, k = count; k > 0; i = inc(i), k--)
  416. if (o.equals(items[i]))
  417. return true;
  418. return false;
  419. } finally {
  420. lock.unlock();
  421. }
  422. }
  423. /**
  424. * Returns an array containing all of the elements in this queue, in
  425. * proper sequence.
  426. *
  427. * <p>The returned array will be "safe" in that no references to it are
  428. * maintained by this queue. (In other words, this method must allocate
  429. * a new array). The caller is thus free to modify the returned array.
  430. *
  431. * <p>This method acts as bridge between array-based and collection-based
  432. * APIs.
  433. *
  434. * @return an array containing all of the elements in this queue
  435. */
  436. public Object[] toArray() {
  437. final Object[] items = this.items;
  438. final ReentrantLock lock = this.lock;
  439. lock.lock();
  440. try {
  441. final int count = this.count;
  442. Object[] a = new Object[count];
  443. for (int i = takeIndex, k = 0; k < count; i = inc(i), k++)
  444. a[k] = items[i];
  445. return a;
  446. } finally {
  447. lock.unlock();
  448. }
  449. }
  450. /**
  451. * Returns an array containing all of the elements in this queue, in
  452. * proper sequence; the runtime type of the returned array is that of
  453. * the specified array. If the queue fits in the specified array, it
  454. * is returned therein. Otherwise, a new array is allocated with the
  455. * runtime type of the specified array and the size of this queue.
  456. *
  457. * <p>If this queue fits in the specified array with room to spare
  458. * (i.e., the array has more elements than this queue), the element in
  459. * the array immediately following the end of the queue is set to
  460. * {@code null}.
  461. *
  462. * <p>Like the {@link #toArray()} method, this method acts as bridge between
  463. * array-based and collection-based APIs. Further, this method allows
  464. * precise control over the runtime type of the output array, and may,
  465. * under certain circumstances, be used to save allocation costs.
  466. *
  467. * <p>Suppose {@code x} is a queue known to contain only strings.
  468. * The following code can be used to dump the queue into a newly
  469. * allocated array of {@code String}:
  470. *
  471. * <pre>
  472. * String[] y = x.toArray(new String[0]);</pre>
  473. * <p>
  474. * Note that {@code toArray(new Object[0])} is identical in function to
  475. * {@code toArray()}.
  476. *
  477. * @param a the array into which the elements of the queue are to
  478. * be stored, if it is big enough; otherwise, a new array of the
  479. * same runtime type is allocated for this purpose
  480. * @return an array containing all of the elements in this queue
  481. * @throws ArrayStoreException if the runtime type of the specified array
  482. * is not a supertype of the runtime type of every element in
  483. * this queue
  484. * @throws NullPointerException if the specified array is null
  485. */
  486. @SuppressWarnings("unchecked")
  487. public <T> T[] toArray(T[] a) {
  488. final Object[] items = this.items;
  489. final ReentrantLock lock = this.lock;
  490. lock.lock();
  491. try {
  492. final int count = this.count;
  493. final int len = a.length;
  494. if (len < count)
  495. a = (T[]) java.lang.reflect.Array.newInstance(
  496. a.getClass().getComponentType(), count);
  497. for (int i = takeIndex, k = 0; k < count; i = inc(i), k++)
  498. a[k] = (T) items[i];
  499. if (len > count)
  500. a[count] = null;
  501. return a;
  502. } finally {
  503. lock.unlock();
  504. }
  505. }
  506. public String toString() {
  507. final ReentrantLock lock = this.lock;
  508. lock.lock();
  509. try {
  510. int k = count;
  511. if (k == 0)
  512. return "[]";
  513. StringBuilder sb = new StringBuilder();
  514. sb.append('[');
  515. for (int i = takeIndex; ; i = inc(i)) {
  516. Object e = items[i];
  517. sb.append(e == this ? "(this Collection)" : e);
  518. if (--k == 0)
  519. return sb.append(']').toString();
  520. sb.append(',').append(' ');
  521. }
  522. } finally {
  523. lock.unlock();
  524. }
  525. }
  526. /**
  527. * Atomically removes all of the elements from this queue.
  528. * The queue will be empty after this call returns.
  529. */
  530. public void clear() {
  531. final Object[] items = this.items;
  532. final ReentrantLock lock = this.lock;
  533. lock.lock();
  534. try {
  535. for (int i = takeIndex, k = count; k > 0; i = inc(i), k--)
  536. items[i] = null;
  537. count = 0;
  538. putIndex = 0;
  539. takeIndex = 0;
  540. notFull.signalAll();
  541. } finally {
  542. lock.unlock();
  543. }
  544. }
  545. /**
  546. * @throws UnsupportedOperationException {@inheritDoc}
  547. * @throws ClassCastException {@inheritDoc}
  548. * @throws NullPointerException {@inheritDoc}
  549. * @throws IllegalArgumentException {@inheritDoc}
  550. */
  551. public int drainTo(Collection<? super E> c) {
  552. checkNotNull(c);
  553. if (c == this)
  554. throw new IllegalArgumentException();
  555. final Object[] items = this.items;
  556. final ReentrantLock lock = this.lock;
  557. lock.lock();
  558. try {
  559. int i = takeIndex;
  560. int n = 0;
  561. int max = count;
  562. while (n < max) {
  563. c.add(this.<E>cast(items[i]));
  564. items[i] = null;
  565. i = inc(i);
  566. ++n;
  567. }
  568. if (n > 0) {
  569. count = 0;
  570. putIndex = 0;
  571. takeIndex = 0;
  572. notFull.signalAll();
  573. }
  574. return n;
  575. } finally {
  576. lock.unlock();
  577. }
  578. }
  579. /**
  580. * @throws UnsupportedOperationException {@inheritDoc}
  581. * @throws ClassCastException {@inheritDoc}
  582. * @throws NullPointerException {@inheritDoc}
  583. * @throws IllegalArgumentException {@inheritDoc}
  584. */
  585. public int drainTo(Collection<? super E> c, int maxElements) {
  586. checkNotNull(c);
  587. if (c == this)
  588. throw new IllegalArgumentException();
  589. if (maxElements <= 0)
  590. return 0;
  591. final Object[] items = this.items;
  592. final ReentrantLock lock = this.lock;
  593. lock.lock();
  594. try {
  595. int i = takeIndex;
  596. int n = 0;
  597. int max = (maxElements < count) ? maxElements : count;
  598. while (n < max) {
  599. c.add(this.<E>cast(items[i]));
  600. items[i] = null;
  601. i = inc(i);
  602. ++n;
  603. }
  604. if (n > 0) {
  605. count -= n;
  606. takeIndex = i;
  607. notFull.signalAll();
  608. }
  609. return n;
  610. } finally {
  611. lock.unlock();
  612. }
  613. }
  614. /**
  615. * Returns an iterator over the elements in this queue in proper sequence.
  616. * The elements will be returned in order from first (head) to last (tail).
  617. *
  618. * <p>The returned {@code Iterator} is a "weakly consistent" iterator that
  619. * will never throw {@link java.util.ConcurrentModificationException
  620. * ConcurrentModificationException},
  621. * and guarantees to traverse elements as they existed upon
  622. * construction of the iterator, and may (but is not guaranteed to)
  623. * reflect any modifications subsequent to construction.
  624. *
  625. * @return an iterator over the elements in this queue in proper sequence
  626. */
  627. public Iterator<E> iterator() {
  628. return new Itr();
  629. }
  630. /**
  631. * Iterator for Target. To maintain weak consistency
  632. * with respect to puts and takes, we (1) read ahead one slot, so
  633. * as to not report hasNext true but then not have an element to
  634. * return -- however we later recheck this slot to use the most
  635. * current value; (2) ensure that each array slot is traversed at
  636. * most once (by tracking "remaining" elements); (3) skip over
  637. * null slots, which can occur if takes race ahead of iterators.
  638. * However, for circular array-based queues, we cannot rely on any
  639. * well established definition of what it means to be weakly
  640. * consistent with respect to interior removes since these may
  641. * require slot overwrites in the process of sliding elements to
  642. * cover gaps. So we settle for resiliency, operating on
  643. * established apparent nexts, which may miss some elements that
  644. * have moved between calls to next.
  645. */
  646. private class Itr implements Iterator<E> {
  647. private int remaining; // Number of elements yet to be returned
  648. private int nextIndex; // Index of element to be returned by next
  649. private E nextItem; // Element to be returned by next call to next
  650. private E lastItem; // Element returned by last call to next
  651. private int lastRet; // Index of last element returned, or -1 if none
  652. Itr() {
  653. final ReentrantLock lock = InstrumentationTarget.this.lock;
  654. lock.lock();
  655. try {
  656. lastRet = -1;
  657. if ((remaining = count) > 0)
  658. nextItem = itemAt(nextIndex = takeIndex);
  659. } finally {
  660. lock.unlock();
  661. }
  662. }
  663. public boolean hasNext() {
  664. return remaining > 0;
  665. }
  666. public E next() {
  667. final ReentrantLock lock = InstrumentationTarget.this.lock;
  668. lock.lock();
  669. try {
  670. if (remaining <= 0)
  671. throw new NoSuchElementException();
  672. lastRet = nextIndex;
  673. E x = itemAt(nextIndex); // check for fresher value
  674. if (x == null) {
  675. x = nextItem; // we are forced to report old value
  676. lastItem = null; // but ensure remove fails
  677. } else
  678. lastItem = x;
  679. while (--remaining > 0 && // skip over nulls
  680. (nextItem = itemAt(nextIndex = inc(nextIndex))) == null)
  681. ;
  682. return x;
  683. } finally {
  684. lock.unlock();
  685. }
  686. }
  687. public void remove() {
  688. final ReentrantLock lock = InstrumentationTarget.this.lock;
  689. lock.lock();
  690. try {
  691. int i = lastRet;
  692. if (i == -1)
  693. throw new IllegalStateException();
  694. lastRet = -1;
  695. E x = lastItem;
  696. lastItem = null;
  697. // only remove if item still at index
  698. if (x != null && x == items[i]) {
  699. boolean removingHead = (i == takeIndex);
  700. removeAt(i);
  701. if (!removingHead)
  702. nextIndex = dec(nextIndex);
  703. }
  704. } finally {
  705. lock.unlock();
  706. }
  707. }
  708. }
  709. }