You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@commons.apache.org by gg...@apache.org on 2019/08/10 22:26:46 UTC
svn commit: r1048500 [24/39] - in
/websites/production/commons/content/proper: commons-pool/
commons-pool/apidocs/ commons-pool/apidocs/org/apache/commons/pool2/
commons-pool/apidocs/org/apache/commons/pool2/class-use/
commons-pool/apidocs/org/apache/c...
Added: websites/production/commons/content/proper/commons-pool/jacoco/org.apache.commons.pool2.impl/LinkedBlockingDeque.java.html
==============================================================================
--- websites/production/commons/content/proper/commons-pool/jacoco/org.apache.commons.pool2.impl/LinkedBlockingDeque.java.html (added)
+++ websites/production/commons/content/proper/commons-pool/jacoco/org.apache.commons.pool2.impl/LinkedBlockingDeque.java.html Sat Aug 10 22:26:44 2019
@@ -0,0 +1,1424 @@
+<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en"><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/><link rel="stylesheet" href="../jacoco-resources/report.css" type="text/css"/><link rel="shortcut icon" href="../jacoco-resources/report.gif" type="image/gif"/><title>LinkedBlockingDeque.java</title><link rel="stylesheet" href="../jacoco-resources/prettify.css" type="text/css"/><script type="text/javascript" src="../jacoco-resources/prettify.js"></script></head><body onload="window['PR_TAB_WIDTH']=4;prettyPrint()"><div class="breadcrumb" id="breadcrumb"><span class="info"><a href="../jacoco-sessions.html" class="el_session">Sessions</a></span><a href="../index.html" class="el_report">Apache Commons Pool</a> > <a href="index.source.html" class="el_package">org.apache.commons.pool2.impl</a> > <span class="el_so
urce">LinkedBlockingDeque.java</span></div><h1>LinkedBlockingDeque.java</h1><pre class="source lang-java linenums">/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.pool2.impl;
+
+import java.io.Serializable;
+import java.util.AbstractQueue;
+import java.util.Collection;
+import java.util.Deque;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Condition;
+
+/**
+ * An optionally-bounded {@linkplain java.util.concurrent.BlockingDeque blocking
+ * deque} based on linked nodes.
+ *
+ * <p> The optional capacity bound constructor argument serves as a
+ * way to prevent excessive expansion. The capacity, if unspecified,
+ * is equal to {@link Integer#MAX_VALUE}. Linked nodes are
+ * dynamically created upon each insertion unless this would bring the
+ * deque above capacity.
+ *
+ * <p>Most operations run in constant time (ignoring time spent
+ * blocking). Exceptions include {@link #remove(Object) remove},
+ * {@link #removeFirstOccurrence removeFirstOccurrence}, {@link
+ * #removeLastOccurrence removeLastOccurrence}, {@link #contains
+ * contains}, {@link #iterator iterator.remove()}, and the bulk
+ * operations, all of which run in linear time.
+ *
+ * <p>This class and its iterator implement all of the
+ * <em>optional</em> methods of the {@link Collection} and {@link
+ * Iterator} interfaces.
+ *
+ * <p>This class is a member of the
+ * <a href="{@docRoot}/../technotes/guides/collections/index.html">
+ * Java Collections Framework</a>.
+ *
+ * @param <E> the type of elements held in this collection
+ *
+ * Note: This was copied from Apache Harmony and modified to suit the needs of
+ * Commons Pool.
+ *
+ * @since 2.0
+ */
+class LinkedBlockingDeque<E> extends AbstractQueue<E>
+ implements Deque<E>, Serializable {
+
+ /*
+ * Implemented as a simple doubly-linked list protected by a
+ * single lock and using conditions to manage blocking.
+ *
+ * To implement weakly consistent iterators, it appears we need to
+ * keep all Nodes GC-reachable from a predecessor dequeued Node.
+ * That would cause two problems:
+ * - allow a rogue Iterator to cause unbounded memory retention
+ * - cause cross-generational linking of old Nodes to new Nodes if
+ * a Node was tenured while live, which generational GCs have a
+ * hard time dealing with, causing repeated major collections.
+ * However, only non-deleted Nodes need to be reachable from
+ * dequeued Nodes, and reachability does not necessarily have to
+ * be of the kind understood by the GC. We use the trick of
+ * linking a Node that has just been dequeued to itself. Such a
+ * self-link implicitly means to jump to "first" (for next links)
+ * or "last" (for prev links).
+ */
+
+ /*
+ * We have "diamond" multiple interface/abstract class inheritance
+ * here, and that introduces ambiguities. Often we want the
+ * BlockingDeque javadoc combined with the AbstractQueue
+ * implementation, so a lot of method specs are duplicated here.
+ */
+
+ private static final long serialVersionUID = -387911632671998426L;
+
+ /**
+ * Doubly-linked list node class.
+ *
+ * @param <E> node item type
+ */
+ private static final class Node<E> {
+ /**
+ * The item, or null if this node has been removed.
+ */
+ E item;
+
+ /**
+ * One of:
+ * - the real predecessor Node
+ * - this Node, meaning the predecessor is tail
+ * - null, meaning there is no predecessor
+ */
+ Node<E> prev;
+
+ /**
+ * One of:
+ * - the real successor Node
+ * - this Node, meaning the successor is head
+ * - null, meaning there is no successor
+ */
+ Node<E> next;
+
+ /**
+ * Create a new list node.
+ *
+ * @param x The list item
+ * @param p Previous item
+ * @param n Next item
+ */
+<span class="fc" id="L125"> Node(final E x, final Node<E> p, final Node<E> n) {</span>
+<span class="fc" id="L126"> item = x;</span>
+<span class="fc" id="L127"> prev = p;</span>
+<span class="fc" id="L128"> next = n;</span>
+<span class="fc" id="L129"> }</span>
+ }
+
+ /**
+ * Pointer to first node.
+ * Invariant: (first == null && last == null) ||
+ * (first.prev == null && first.item != null)
+ */
+ private transient Node<E> first; // @GuardedBy("lock")
+
+ /**
+ * Pointer to last node.
+ * Invariant: (first == null && last == null) ||
+ * (last.next == null && last.item != null)
+ */
+ private transient Node<E> last; // @GuardedBy("lock")
+
+ /** Number of items in the deque */
+ private transient int count; // @GuardedBy("lock")
+
+ /** Maximum number of items in the deque */
+ private final int capacity;
+
+ /** Main lock guarding all access */
+ private final InterruptibleReentrantLock lock;
+
+ /** Condition for waiting takes */
+ private final Condition notEmpty;
+
+ /** Condition for waiting puts */
+ private final Condition notFull;
+
+ /**
+ * Creates a {@code LinkedBlockingDeque} with a capacity of
+ * {@link Integer#MAX_VALUE}.
+ */
+ public LinkedBlockingDeque() {
+<span class="fc" id="L166"> this(Integer.MAX_VALUE);</span>
+<span class="fc" id="L167"> }</span>
+
+ /**
+ * Creates a {@code LinkedBlockingDeque} with a capacity of
+ * {@link Integer#MAX_VALUE} and the given fairness policy.
+ * @param fairness true means threads waiting on the deque should be served
+ * as if waiting in a FIFO request queue
+ */
+ public LinkedBlockingDeque(final boolean fairness) {
+<span class="fc" id="L176"> this(Integer.MAX_VALUE, fairness);</span>
+<span class="fc" id="L177"> }</span>
+
+ /**
+ * Creates a {@code LinkedBlockingDeque} with the given (fixed) capacity.
+ *
+ * @param capacity the capacity of this deque
+ * @throws IllegalArgumentException if {@code capacity} is less than 1
+ */
+ public LinkedBlockingDeque(final int capacity) {
+<span class="fc" id="L186"> this(capacity, false);</span>
+<span class="fc" id="L187"> }</span>
+
+ /**
+ * Creates a {@code LinkedBlockingDeque} with the given (fixed) capacity
+ * and fairness policy.
+ *
+ * @param capacity the capacity of this deque
+ * @param fairness true means threads waiting on the deque should be served
+ * as if waiting in a FIFO request queue
+ * @throws IllegalArgumentException if {@code capacity} is less than 1
+ */
+<span class="fc" id="L198"> public LinkedBlockingDeque(final int capacity, final boolean fairness) {</span>
+<span class="pc bpc" id="L199" title="1 of 2 branches missed."> if (capacity <= 0) {</span>
+<span class="nc" id="L200"> throw new IllegalArgumentException();</span>
+ }
+<span class="fc" id="L202"> this.capacity = capacity;</span>
+<span class="fc" id="L203"> lock = new InterruptibleReentrantLock(fairness);</span>
+<span class="fc" id="L204"> notEmpty = lock.newCondition();</span>
+<span class="fc" id="L205"> notFull = lock.newCondition();</span>
+<span class="fc" id="L206"> }</span>
+
+ /**
+ * Creates a {@code LinkedBlockingDeque} with a capacity of
+ * {@link Integer#MAX_VALUE}, initially containing the elements of
+ * the given collection, added in traversal order of the
+ * collection's iterator.
+ *
+ * @param c the collection of elements to initially contain
+ * @throws NullPointerException if the specified collection or any
+ * of its elements are null
+ */
+ public LinkedBlockingDeque(final Collection<? extends E> c) {
+<span class="fc" id="L219"> this(Integer.MAX_VALUE);</span>
+<span class="fc" id="L220"> lock.lock(); // Never contended, but necessary for visibility</span>
+ try {
+<span class="fc bfc" id="L222" title="All 2 branches covered."> for (final E e : c) {</span>
+<span class="fc bfc" id="L223" title="All 2 branches covered."> if (e == null) {</span>
+<span class="fc" id="L224"> throw new NullPointerException();</span>
+ }
+<span class="pc bpc" id="L226" title="1 of 2 branches missed."> if (!linkLast(e)) {</span>
+<span class="nc" id="L227"> throw new IllegalStateException("Deque full");</span>
+ }
+<span class="fc" id="L229"> }</span>
+ } finally {
+<span class="fc" id="L231"> lock.unlock();</span>
+ }
+<span class="fc" id="L233"> }</span>
+
+
+ // Basic linking and unlinking operations, called only while holding lock
+
+ /**
+ * Links provided element as first element, or returns false if full.
+ *
+ * @param e The element to link as the first element.
+ *
+ * @return {@code true} if successful, otherwise {@code false}
+ */
+ private boolean linkFirst(final E e) {
+ // assert lock.isHeldByCurrentThread();
+<span class="fc bfc" id="L247" title="All 2 branches covered."> if (count >= capacity) {</span>
+<span class="fc" id="L248"> return false;</span>
+ }
+<span class="fc" id="L250"> final Node<E> f = first;</span>
+<span class="fc" id="L251"> final Node<E> x = new Node<>(e, null, f);</span>
+<span class="fc" id="L252"> first = x;</span>
+<span class="fc bfc" id="L253" title="All 2 branches covered."> if (last == null) {</span>
+<span class="fc" id="L254"> last = x;</span>
+ } else {
+<span class="fc" id="L256"> f.prev = x;</span>
+ }
+<span class="fc" id="L258"> ++count;</span>
+<span class="fc" id="L259"> notEmpty.signal();</span>
+<span class="fc" id="L260"> return true;</span>
+ }
+
+ /**
+ * Links provided element as last element, or returns false if full.
+ *
+ * @param e The element to link as the last element.
+ *
+ * @return {@code true} if successful, otherwise {@code false}
+ */
+ private boolean linkLast(final E e) {
+ // assert lock.isHeldByCurrentThread();
+<span class="fc bfc" id="L272" title="All 2 branches covered."> if (count >= capacity) {</span>
+<span class="fc" id="L273"> return false;</span>
+ }
+<span class="fc" id="L275"> final Node<E> l = last;</span>
+<span class="fc" id="L276"> final Node<E> x = new Node<>(e, l, null);</span>
+<span class="fc" id="L277"> last = x;</span>
+<span class="fc bfc" id="L278" title="All 2 branches covered."> if (first == null) {</span>
+<span class="fc" id="L279"> first = x;</span>
+ } else {
+<span class="fc" id="L281"> l.next = x;</span>
+ }
+<span class="fc" id="L283"> ++count;</span>
+<span class="fc" id="L284"> notEmpty.signal();</span>
+<span class="fc" id="L285"> return true;</span>
+ }
+
+ /**
+ * Removes and returns the first element, or null if empty.
+ *
+ * @return The first element or {@code null} if empty
+ */
+ private E unlinkFirst() {
+ // assert lock.isHeldByCurrentThread();
+<span class="fc" id="L295"> final Node<E> f = first;</span>
+<span class="fc bfc" id="L296" title="All 2 branches covered."> if (f == null) {</span>
+<span class="fc" id="L297"> return null;</span>
+ }
+<span class="fc" id="L299"> final Node<E> n = f.next;</span>
+<span class="fc" id="L300"> final E item = f.item;</span>
+<span class="fc" id="L301"> f.item = null;</span>
+<span class="fc" id="L302"> f.next = f; // help GC</span>
+<span class="fc" id="L303"> first = n;</span>
+<span class="fc bfc" id="L304" title="All 2 branches covered."> if (n == null) {</span>
+<span class="fc" id="L305"> last = null;</span>
+ } else {
+<span class="fc" id="L307"> n.prev = null;</span>
+ }
+<span class="fc" id="L309"> --count;</span>
+<span class="fc" id="L310"> notFull.signal();</span>
+<span class="fc" id="L311"> return item;</span>
+ }
+
+ /**
+ * Removes and returns the last element, or null if empty.
+ *
+ * @return The first element or {@code null} if empty
+ */
+ private E unlinkLast() {
+ // assert lock.isHeldByCurrentThread();
+<span class="fc" id="L321"> final Node<E> l = last;</span>
+<span class="fc bfc" id="L322" title="All 2 branches covered."> if (l == null) {</span>
+<span class="fc" id="L323"> return null;</span>
+ }
+<span class="fc" id="L325"> final Node<E> p = l.prev;</span>
+<span class="fc" id="L326"> final E item = l.item;</span>
+<span class="fc" id="L327"> l.item = null;</span>
+<span class="fc" id="L328"> l.prev = l; // help GC</span>
+<span class="fc" id="L329"> last = p;</span>
+<span class="fc bfc" id="L330" title="All 2 branches covered."> if (p == null) {</span>
+<span class="fc" id="L331"> first = null;</span>
+ } else {
+<span class="fc" id="L333"> p.next = null;</span>
+ }
+<span class="fc" id="L335"> --count;</span>
+<span class="fc" id="L336"> notFull.signal();</span>
+<span class="fc" id="L337"> return item;</span>
+ }
+
+ /**
+ * Unlinks the provided node.
+ *
+ * @param x The node to unlink
+ */
+ private void unlink(final Node<E> x) {
+ // assert lock.isHeldByCurrentThread();
+<span class="fc" id="L347"> final Node<E> p = x.prev;</span>
+<span class="fc" id="L348"> final Node<E> n = x.next;</span>
+<span class="fc bfc" id="L349" title="All 2 branches covered."> if (p == null) {</span>
+<span class="fc" id="L350"> unlinkFirst();</span>
+<span class="fc bfc" id="L351" title="All 2 branches covered."> } else if (n == null) {</span>
+<span class="fc" id="L352"> unlinkLast();</span>
+ } else {
+<span class="fc" id="L354"> p.next = n;</span>
+<span class="fc" id="L355"> n.prev = p;</span>
+<span class="fc" id="L356"> x.item = null;</span>
+ // Don't mess with x's links. They may still be in use by
+ // an iterator.
+<span class="fc" id="L359"> --count;</span>
+<span class="fc" id="L360"> notFull.signal();</span>
+ }
+<span class="fc" id="L362"> }</span>
+
+ // BlockingDeque methods
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void addFirst(final E e) {
+<span class="fc bfc" id="L371" title="All 2 branches covered."> if (!offerFirst(e)) {</span>
+<span class="fc" id="L372"> throw new IllegalStateException("Deque full");</span>
+ }
+<span class="fc" id="L374"> }</span>
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void addLast(final E e) {
+<span class="fc bfc" id="L381" title="All 2 branches covered."> if (!offerLast(e)) {</span>
+<span class="fc" id="L382"> throw new IllegalStateException("Deque full");</span>
+ }
+<span class="fc" id="L384"> }</span>
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean offerFirst(final E e) {
+<span class="fc bfc" id="L391" title="All 2 branches covered."> if (e == null) {</span>
+<span class="fc" id="L392"> throw new NullPointerException();</span>
+ }
+<span class="fc" id="L394"> lock.lock();</span>
+ try {
+<span class="fc" id="L396"> return linkFirst(e);</span>
+ } finally {
+<span class="fc" id="L398"> lock.unlock();</span>
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean offerLast(final E e) {
+<span class="fc bfc" id="L407" title="All 2 branches covered."> if (e == null) {</span>
+<span class="fc" id="L408"> throw new NullPointerException();</span>
+ }
+<span class="fc" id="L410"> lock.lock();</span>
+ try {
+<span class="fc" id="L412"> return linkLast(e);</span>
+ } finally {
+<span class="fc" id="L414"> lock.unlock();</span>
+ }
+ }
+
+ /**
+ * Links the provided element as the first in the queue, waiting until there
+ * is space to do so if the queue is full.
+ *
+ * @param e element to link
+ *
+ * @throws NullPointerException if e is null
+ * @throws InterruptedException if the thread is interrupted whilst waiting
+ * for space
+ */
+ public void putFirst(final E e) throws InterruptedException {
+<span class="fc bfc" id="L429" title="All 2 branches covered."> if (e == null) {</span>
+<span class="fc" id="L430"> throw new NullPointerException();</span>
+ }
+<span class="fc" id="L432"> lock.lock();</span>
+ try {
+<span class="pc bpc" id="L434" title="1 of 2 branches missed."> while (!linkFirst(e)) {</span>
+<span class="nc" id="L435"> notFull.await();</span>
+ }
+ } finally {
+<span class="fc" id="L438"> lock.unlock();</span>
+ }
+<span class="fc" id="L440"> }</span>
+
+ /**
+ * Links the provided element as the last in the queue, waiting until there
+ * is space to do so if the queue is full.
+ *
+ * @param e element to link
+ *
+ * @throws NullPointerException if e is null
+ * @throws InterruptedException if the thread is interrupted whilst waiting
+ * for space
+ */
+ public void putLast(final E e) throws InterruptedException {
+<span class="fc bfc" id="L453" title="All 2 branches covered."> if (e == null) {</span>
+<span class="fc" id="L454"> throw new NullPointerException();</span>
+ }
+<span class="fc" id="L456"> lock.lock();</span>
+ try {
+<span class="pc bpc" id="L458" title="1 of 2 branches missed."> while (!linkLast(e)) {</span>
+<span class="nc" id="L459"> notFull.await();</span>
+ }
+ } finally {
+<span class="fc" id="L462"> lock.unlock();</span>
+ }
+<span class="fc" id="L464"> }</span>
+
+ /**
+ * Links the provided element as the first in the queue, waiting up to the
+ * specified time to do so if the queue is full.
+ *
+ * @param e element to link
+ * @param timeout length of time to wait
+ * @param unit units that timeout is expressed in
+ *
+ * @return {@code true} if successful, otherwise {@code false}
+ *
+ * @throws NullPointerException if e is null
+ * @throws InterruptedException if the thread is interrupted whilst waiting
+ * for space
+ */
+ public boolean offerFirst(final E e, final long timeout, final TimeUnit unit)
+ throws InterruptedException {
+<span class="pc bpc" id="L482" title="1 of 2 branches missed."> if (e == null) {</span>
+<span class="nc" id="L483"> throw new NullPointerException();</span>
+ }
+<span class="fc" id="L485"> long nanos = unit.toNanos(timeout);</span>
+<span class="fc" id="L486"> lock.lockInterruptibly();</span>
+ try {
+<span class="fc bfc" id="L488" title="All 2 branches covered."> while (!linkFirst(e)) {</span>
+<span class="fc bfc" id="L489" title="All 2 branches covered."> if (nanos <= 0) {</span>
+<span class="fc" id="L490"> return false;</span>
+ }
+<span class="fc" id="L492"> nanos = notFull.awaitNanos(nanos);</span>
+ }
+<span class="fc" id="L494"> return true;</span>
+ } finally {
+<span class="fc" id="L496"> lock.unlock();</span>
+ }
+ }
+
+ /**
+ * Links the provided element as the last in the queue, waiting up to the
+ * specified time to do so if the queue is full.
+ *
+ * @param e element to link
+ * @param timeout length of time to wait
+ * @param unit units that timeout is expressed in
+ *
+ * @return {@code true} if successful, otherwise {@code false}
+ *
+ * @throws NullPointerException if e is null
+ * @throws InterruptedException if the thread is interrupted whist waiting
+ * for space
+ */
+ public boolean offerLast(final E e, final long timeout, final TimeUnit unit)
+ throws InterruptedException {
+<span class="fc bfc" id="L516" title="All 2 branches covered."> if (e == null) {</span>
+<span class="fc" id="L517"> throw new NullPointerException();</span>
+ }
+<span class="fc" id="L519"> long nanos = unit.toNanos(timeout);</span>
+<span class="fc" id="L520"> lock.lockInterruptibly();</span>
+ try {
+<span class="fc bfc" id="L522" title="All 2 branches covered."> while (!linkLast(e)) {</span>
+<span class="fc bfc" id="L523" title="All 2 branches covered."> if (nanos <= 0) {</span>
+<span class="fc" id="L524"> return false;</span>
+ }
+<span class="fc" id="L526"> nanos = notFull.awaitNanos(nanos);</span>
+ }
+<span class="fc" id="L528"> return true;</span>
+ } finally {
+<span class="fc" id="L530"> lock.unlock();</span>
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public E removeFirst() {
+<span class="fc" id="L539"> final E x = pollFirst();</span>
+<span class="fc bfc" id="L540" title="All 2 branches covered."> if (x == null) {</span>
+<span class="fc" id="L541"> throw new NoSuchElementException();</span>
+ }
+<span class="fc" id="L543"> return x;</span>
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public E removeLast() {
+<span class="fc" id="L551"> final E x = pollLast();</span>
+<span class="fc bfc" id="L552" title="All 2 branches covered."> if (x == null) {</span>
+<span class="fc" id="L553"> throw new NoSuchElementException();</span>
+ }
+<span class="fc" id="L555"> return x;</span>
+ }
+
+ @Override
+ public E pollFirst() {
+<span class="fc" id="L560"> lock.lock();</span>
+ try {
+<span class="fc" id="L562"> return unlinkFirst();</span>
+ } finally {
+<span class="fc" id="L564"> lock.unlock();</span>
+ }
+ }
+
+ @Override
+ public E pollLast() {
+<span class="fc" id="L570"> lock.lock();</span>
+ try {
+<span class="fc" id="L572"> return unlinkLast();</span>
+ } finally {
+<span class="fc" id="L574"> lock.unlock();</span>
+ }
+ }
+
+ /**
+ * Unlinks the first element in the queue, waiting until there is an element
+ * to unlink if the queue is empty.
+ *
+ * @return the unlinked element
+ * @throws InterruptedException if the current thread is interrupted
+ */
+ public E takeFirst() throws InterruptedException {
+<span class="fc" id="L586"> lock.lock();</span>
+ try {
+ E x;
+<span class="fc bfc" id="L589" title="All 2 branches covered."> while ( (x = unlinkFirst()) == null) {</span>
+<span class="fc" id="L590"> notEmpty.await();</span>
+ }
+<span class="fc" id="L592"> return x;</span>
+ } finally {
+<span class="fc" id="L594"> lock.unlock();</span>
+ }
+ }
+
+ /**
+ * Unlinks the last element in the queue, waiting until there is an element
+ * to unlink if the queue is empty.
+ *
+ * @return the unlinked element
+ * @throws InterruptedException if the current thread is interrupted
+ */
+ public E takeLast() throws InterruptedException {
+<span class="fc" id="L606"> lock.lock();</span>
+ try {
+ E x;
+<span class="pc bpc" id="L609" title="1 of 2 branches missed."> while ( (x = unlinkLast()) == null) {</span>
+<span class="nc" id="L610"> notEmpty.await();</span>
+ }
+<span class="fc" id="L612"> return x;</span>
+ } finally {
+<span class="fc" id="L614"> lock.unlock();</span>
+ }
+ }
+
+ /**
+ * Unlinks the first element in the queue, waiting up to the specified time
+ * to do so if the queue is empty.
+ *
+ * @param timeout length of time to wait
+ * @param unit units that timeout is expressed in
+ *
+ * @return the unlinked element
+ * @throws InterruptedException if the current thread is interrupted
+ */
+ public E pollFirst(final long timeout, final TimeUnit unit)
+ throws InterruptedException {
+<span class="fc" id="L630"> long nanos = unit.toNanos(timeout);</span>
+<span class="fc" id="L631"> lock.lockInterruptibly();</span>
+ try {
+ E x;
+<span class="fc bfc" id="L634" title="All 2 branches covered."> while ( (x = unlinkFirst()) == null) {</span>
+<span class="fc bfc" id="L635" title="All 2 branches covered."> if (nanos <= 0) {</span>
+<span class="fc" id="L636"> return null;</span>
+ }
+<span class="fc" id="L638"> nanos = notEmpty.awaitNanos(nanos);</span>
+ }
+<span class="fc" id="L640"> return x;</span>
+ } finally {
+<span class="fc" id="L642"> lock.unlock();</span>
+ }
+ }
+
+ /**
+ * Unlinks the last element in the queue, waiting up to the specified time
+ * to do so if the queue is empty.
+ *
+ * @param timeout length of time to wait
+ * @param unit units that timeout is expressed in
+ *
+ * @return the unlinked element
+ * @throws InterruptedException if the current thread is interrupted
+ */
+ public E pollLast(final long timeout, final TimeUnit unit)
+ throws InterruptedException {
+<span class="fc" id="L658"> long nanos = unit.toNanos(timeout);</span>
+<span class="fc" id="L659"> lock.lockInterruptibly();</span>
+ try {
+ E x;
+<span class="pc bpc" id="L662" title="1 of 2 branches missed."> while ( (x = unlinkLast()) == null) {</span>
+<span class="fc bfc" id="L663" title="All 2 branches covered."> if (nanos <= 0) {</span>
+<span class="fc" id="L664"> return null;</span>
+ }
+<span class="fc" id="L666"> nanos = notEmpty.awaitNanos(nanos);</span>
+ }
+<span class="nc" id="L668"> return x;</span>
+ } finally {
+<span class="fc" id="L670"> lock.unlock();</span>
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public E getFirst() {
+<span class="fc" id="L679"> final E x = peekFirst();</span>
+<span class="fc bfc" id="L680" title="All 2 branches covered."> if (x == null) {</span>
+<span class="fc" id="L681"> throw new NoSuchElementException();</span>
+ }
+<span class="fc" id="L683"> return x;</span>
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public E getLast() {
+<span class="fc" id="L691"> final E x = peekLast();</span>
+<span class="fc bfc" id="L692" title="All 2 branches covered."> if (x == null) {</span>
+<span class="fc" id="L693"> throw new NoSuchElementException();</span>
+ }
+<span class="fc" id="L695"> return x;</span>
+ }
+
+ @Override
+ public E peekFirst() {
+<span class="fc" id="L700"> lock.lock();</span>
+ try {
+<span class="fc bfc" id="L702" title="All 2 branches covered."> return first == null ? null : first.item;</span>
+ } finally {
+<span class="fc" id="L704"> lock.unlock();</span>
+ }
+ }
+
+ @Override
+ public E peekLast() {
+<span class="fc" id="L710"> lock.lock();</span>
+ try {
+<span class="fc bfc" id="L712" title="All 2 branches covered."> return last == null ? null : last.item;</span>
+ } finally {
+<span class="fc" id="L714"> lock.unlock();</span>
+ }
+ }
+
+ @Override
+ public boolean removeFirstOccurrence(final Object o) {
+<span class="pc bpc" id="L720" title="1 of 2 branches missed."> if (o == null) {</span>
+<span class="nc" id="L721"> return false;</span>
+ }
+<span class="fc" id="L723"> lock.lock();</span>
+ try {
+<span class="fc bfc" id="L725" title="All 2 branches covered."> for (Node<E> p = first; p != null; p = p.next) {</span>
+<span class="fc bfc" id="L726" title="All 2 branches covered."> if (o.equals(p.item)) {</span>
+<span class="fc" id="L727"> unlink(p);</span>
+<span class="fc" id="L728"> return true;</span>
+ }
+ }
+<span class="fc" id="L731"> return false;</span>
+ } finally {
+<span class="fc" id="L733"> lock.unlock();</span>
+ }
+ }
+
+ @Override
+ public boolean removeLastOccurrence(final Object o) {
+<span class="fc bfc" id="L739" title="All 2 branches covered."> if (o == null) {</span>
+<span class="fc" id="L740"> return false;</span>
+ }
+<span class="fc" id="L742"> lock.lock();</span>
+ try {
+<span class="pc bfc" id="L744" title="All 2 branches covered."> for (Node<E> p = last; p != null; p = p.prev) {</span>
+<span class="pc bpc" id="L745" title="1 of 2 branches missed."> if (o.equals(p.item)) {</span>
+<span class="fc" id="L746"> unlink(p);</span>
+<span class="fc" id="L747"> return true;</span>
+ }
+ }
+<span class="fc" id="L750"> return false;</span>
+ } finally {
+<span class="fc" id="L752"> lock.unlock();</span>
+ }
+ }
+
+ // BlockingQueue methods
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean add(final E e) {
+<span class="fc" id="L763"> addLast(e);</span>
+<span class="fc" id="L764"> return true;</span>
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean offer(final E e) {
+<span class="fc" id="L772"> return offerLast(e);</span>
+ }
+
+ /**
+ * Links the provided element as the last in the queue, waiting until there
+ * is space to do so if the queue is full.
+ *
+ * <p>This method is equivalent to {@link #putLast(Object)}.
+ *
+ * @param e element to link
+ *
+ * @throws NullPointerException if e is null
+ * @throws InterruptedException if the thread is interrupted whilst waiting
+ * for space
+ */
+ public void put(final E e) throws InterruptedException {
+<span class="fc" id="L788"> putLast(e);</span>
+<span class="fc" id="L789"> }</span>
+
+ /**
+ * Links the provided element as the last in the queue, waiting up to the
+ * specified time to do so if the queue is full.
+ * <p>
+ * This method is equivalent to {@link #offerLast(Object, long, TimeUnit)}
+ *
+ * @param e element to link
+ * @param timeout length of time to wait
+ * @param unit units that timeout is expressed in
+ *
+ * @return {@code true} if successful, otherwise {@code false}
+ *
+ * @throws NullPointerException if e is null
+ * @throws InterruptedException if the thread is interrupted whilst waiting
+ * for space
+ */
+ public boolean offer(final E e, final long timeout, final TimeUnit unit)
+ throws InterruptedException {
+<span class="fc" id="L809"> return offerLast(e, timeout, unit);</span>
+ }
+
+ /**
+ * Retrieves and removes the head of the queue represented by this deque.
+ * This method differs from {@link #poll poll} only in that it throws an
+ * exception if this deque is empty.
+ *
+ * <p>This method is equivalent to {@link #removeFirst() removeFirst}.
+ *
+ * @return the head of the queue represented by this deque
+ * @throws NoSuchElementException if this deque is empty
+ */
+ @Override
+ public E remove() {
+<span class="fc" id="L824"> return removeFirst();</span>
+ }
+
+ @Override
+ public E poll() {
+<span class="fc" id="L829"> return pollFirst();</span>
+ }
+
+ /**
+ * Unlinks the first element in the queue, waiting until there is an element
+ * to unlink if the queue is empty.
+ *
+ * <p>This method is equivalent to {@link #takeFirst()}.
+ *
+ * @return the unlinked element
+ * @throws InterruptedException if the current thread is interrupted
+ */
+ public E take() throws InterruptedException {
+<span class="fc" id="L842"> return takeFirst();</span>
+ }
+
+ /**
+ * Unlinks the first element in the queue, waiting up to the specified time
+ * to do so if the queue is empty.
+ *
+ * <p>This method is equivalent to {@link #pollFirst(long, TimeUnit)}.
+ *
+ * @param timeout length of time to wait
+ * @param unit units that timeout is expressed in
+ *
+ * @return the unlinked element
+ * @throws InterruptedException if the current thread is interrupted
+ */
+ public E poll(final long timeout, final TimeUnit unit) throws InterruptedException {
+<span class="fc" id="L858"> return pollFirst(timeout, unit);</span>
+ }
+
+ /**
+ * Retrieves, but does not remove, the head of the queue represented by
+ * this deque. This method differs from {@link #peek peek} only in that
+ * it throws an exception if this deque is empty.
+ *
+ * <p>This method is equivalent to {@link #getFirst() getFirst}.
+ *
+ * @return the head of the queue represented by this deque
+ * @throws NoSuchElementException if this deque is empty
+ */
+ @Override
+ public E element() {
+<span class="fc" id="L873"> return getFirst();</span>
+ }
+
+ @Override
+ public E peek() {
+<span class="fc" id="L878"> return peekFirst();</span>
+ }
+
+ /**
+ * Returns the number of additional elements that this deque can ideally
+ * (in the absence of memory or resource constraints) accept without
+ * blocking. This is always equal to the initial capacity of this deque
+ * less the current {@code size} of this deque.
+ *
+ * <p>Note that you <em>cannot</em> always tell if an attempt to insert
+ * an element will succeed by inspecting {@code remainingCapacity}
+ * because it may be the case that another thread is about to
+ * insert or remove an element.
+ *
+ * @return The number of additional elements the queue is able to accept
+ */
+ public int remainingCapacity() {
+<span class="fc" id="L895"> lock.lock();</span>
+ try {
+<span class="fc" id="L897"> return capacity - count;</span>
+ } finally {
+<span class="fc" id="L899"> lock.unlock();</span>
+ }
+ }
+
+ /**
+ * Drains the queue to the specified collection.
+ *
+ * @param c The collection to add the elements to
+ *
+ * @return number of elements added to the collection
+ *
+ * @throws UnsupportedOperationException if the add operation is not
+ * supported by the specified collection
+ * @throws ClassCastException if the class of the elements held by this
+ * collection prevents them from being added to the specified
+ * collection
+ * @throws NullPointerException if c is null
+ * @throws IllegalArgumentException if c is this instance
+ */
+ public int drainTo(final Collection<? super E> c) {
+<span class="fc" id="L919"> return drainTo(c, Integer.MAX_VALUE);</span>
+ }
+
+ /**
+ * Drains no more than the specified number of elements from the queue to the
+ * specified collection.
+ *
+ * @param c collection to add the elements to
+ * @param maxElements maximum number of elements to remove from the queue
+ *
+ * @return number of elements added to the collection
+ * @throws UnsupportedOperationException if the add operation is not
+ * supported by the specified collection
+ * @throws ClassCastException if the class of the elements held by this
+ * collection prevents them from being added to the specified
+ * collection
+ * @throws NullPointerException if c is null
+ * @throws IllegalArgumentException if c is this instance
+ */
+ public int drainTo(final Collection<? super E> c, final int maxElements) {
+<span class="pc bpc" id="L939" title="1 of 2 branches missed."> if (c == null) {</span>
+<span class="nc" id="L940"> throw new NullPointerException();</span>
+ }
+<span class="pc bpc" id="L942" title="1 of 2 branches missed."> if (c == this) {</span>
+<span class="nc" id="L943"> throw new IllegalArgumentException();</span>
+ }
+<span class="fc" id="L945"> lock.lock();</span>
+ try {
+<span class="fc" id="L947"> final int n = Math.min(maxElements, count);</span>
+<span class="fc bfc" id="L948" title="All 2 branches covered."> for (int i = 0; i < n; i++) {</span>
+<span class="fc" id="L949"> c.add(first.item); // In this order, in case add() throws.</span>
+<span class="fc" id="L950"> unlinkFirst();</span>
+ }
+<span class="fc" id="L952"> return n;</span>
+ } finally {
+<span class="fc" id="L954"> lock.unlock();</span>
+ }
+ }
+
+ // Stack methods
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void push(final E e) {
+<span class="fc" id="L965"> addFirst(e);</span>
+<span class="fc" id="L966"> }</span>
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public E pop() {
+<span class="fc" id="L973"> return removeFirst();</span>
+ }
+
+ // Collection methods
+
+ /**
+ * Removes the first occurrence of the specified element from this deque.
+ * If the deque does not contain the element, it is unchanged.
+ * More formally, removes the first element {@code e} such that
+ * {@code o.equals(e)} (if such an element exists).
+ * Returns {@code true} if this deque contained the specified element
+ * (or equivalently, if this deque changed as a result of the call).
+ *
+ * <p>This method is equivalent to
+ * {@link #removeFirstOccurrence(Object) removeFirstOccurrence}.
+ *
+ * @param o element to be removed from this deque, if present
+ * @return {@code true} if this deque changed as a result of the call
+ */
+ @Override
+ public boolean remove(final Object o) {
+<span class="fc" id="L994"> return removeFirstOccurrence(o);</span>
+ }
+
+ /**
+ * Returns the number of elements in this deque.
+ *
+ * @return the number of elements in this deque
+ */
+ @Override
+ public int size() {
+<span class="fc" id="L1004"> lock.lock();</span>
+ try {
+<span class="fc" id="L1006"> return count;</span>
+ } finally {
+<span class="fc" id="L1008"> lock.unlock();</span>
+ }
+ }
+
+ /**
+ * Returns {@code true} if this deque contains the specified element.
+ * More formally, returns {@code true} if and only if this deque contains
+ * at least one element {@code e} such that {@code o.equals(e)}.
+ *
+ * @param o object to be checked for containment in this deque
+ * @return {@code true} if this deque contains the specified element
+ */
+ @Override
+ public boolean contains(final Object o) {
+<span class="fc bfc" id="L1022" title="All 2 branches covered."> if (o == null) {</span>
+<span class="fc" id="L1023"> return false;</span>
+ }
+<span class="fc" id="L1025"> lock.lock();</span>
+ try {
+<span class="fc bfc" id="L1027" title="All 2 branches covered."> for (Node<E> p = first; p != null; p = p.next) {</span>
+<span class="fc bfc" id="L1028" title="All 2 branches covered."> if (o.equals(p.item)) {</span>
+<span class="fc" id="L1029"> return true;</span>
+ }
+ }
+<span class="fc" id="L1032"> return false;</span>
+ } finally {
+<span class="fc" id="L1034"> lock.unlock();</span>
+ }
+ }
+
+ /*
+ * TODO: Add support for more efficient bulk operations.
+ *
+ * We don't want to acquire the lock for every iteration, but we
+ * also want other threads a chance to interact with the
+ * collection, especially when count is close to capacity.
+ */
+
+// /**
+// * Adds all of the elements in the specified collection to this
+// * queue. Attempts to addAll of a queue to itself result in
+// * {@code IllegalArgumentException}. Further, the behavior of
+// * this operation is undefined if the specified collection is
+// * modified while the operation is in progress.
+// *
+// * @param c collection containing elements to be added to this queue
+// * @return {@code true} if this queue changed as a result of the call
+// * @throws ClassCastException
+// * @throws NullPointerException
+// * @throws IllegalArgumentException
+// * @throws IllegalStateException
+// * @see #add(Object)
+// */
+// public boolean addAll(Collection<? extends E> c) {
+// if (c == null)
+// throw new NullPointerException();
+// if (c == this)
+// throw new IllegalArgumentException();
+// final ReentrantLock lock = this.lock;
+// lock.lock();
+// try {
+// boolean modified = false;
+// for (E e : c)
+// if (linkLast(e))
+// modified = true;
+// return modified;
+// } finally {
+// lock.unlock();
+// }
+// }
+
+ /**
+ * Returns an array containing all of the elements in this deque, in
+ * proper sequence (from first to last element).
+ *
+ * <p>The returned array will be "safe" in that no references to it are
+ * maintained by this deque. (In other words, this method must allocate
+ * a new array). The caller is thus free to modify the returned array.
+ *
+ * <p>This method acts as bridge between array-based and collection-based
+ * APIs.
+ *
+ * @return an array containing all of the elements in this deque
+ */
+ @Override
+ public Object[] toArray() {
+<span class="fc" id="L1094"> lock.lock();</span>
+ try {
+<span class="fc" id="L1096"> final Object[] a = new Object[count];</span>
+<span class="fc" id="L1097"> int k = 0;</span>
+<span class="fc bfc" id="L1098" title="All 2 branches covered."> for (Node<E> p = first; p != null; p = p.next) {</span>
+<span class="fc" id="L1099"> a[k++] = p.item;</span>
+ }
+<span class="fc" id="L1101"> return a;</span>
+ } finally {
+<span class="fc" id="L1103"> lock.unlock();</span>
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> T[] toArray(T[] a) {
+<span class="fc" id="L1113"> lock.lock();</span>
+ try {
+<span class="fc bfc" id="L1115" title="All 2 branches covered."> if (a.length < count) {</span>
+<span class="fc" id="L1116"> a = (T[])java.lang.reflect.Array.newInstance</span>
+<span class="fc" id="L1117"> (a.getClass().getComponentType(), count);</span>
+ }
+<span class="fc" id="L1119"> int k = 0;</span>
+<span class="fc bfc" id="L1120" title="All 2 branches covered."> for (Node<E> p = first; p != null; p = p.next) {</span>
+<span class="fc" id="L1121"> a[k++] = (T)p.item;</span>
+ }
+<span class="pc bpc" id="L1123" title="1 of 2 branches missed."> if (a.length > k) {</span>
+<span class="nc" id="L1124"> a[k] = null;</span>
+ }
+<span class="fc" id="L1126"> return a;</span>
+ } finally {
+<span class="fc" id="L1128"> lock.unlock();</span>
+ }
+ }
+
+ @Override
+ public String toString() {
+<span class="fc" id="L1134"> lock.lock();</span>
+ try {
+<span class="fc" id="L1136"> return super.toString();</span>
+ } finally {
+<span class="fc" id="L1138"> lock.unlock();</span>
+ }
+ }
+
+ /**
+ * Atomically removes all of the elements from this deque.
+ * The deque will be empty after this call returns.
+ */
+ @Override
+ public void clear() {
+<span class="fc" id="L1148"> lock.lock();</span>
+ try {
+<span class="fc bfc" id="L1150" title="All 2 branches covered."> for (Node<E> f = first; f != null;) {</span>
+<span class="fc" id="L1151"> f.item = null;</span>
+<span class="fc" id="L1152"> final Node<E> n = f.next;</span>
+<span class="fc" id="L1153"> f.prev = null;</span>
+<span class="fc" id="L1154"> f.next = null;</span>
+<span class="fc" id="L1155"> f = n;</span>
+<span class="fc" id="L1156"> }</span>
+<span class="fc" id="L1157"> first = last = null;</span>
+<span class="fc" id="L1158"> count = 0;</span>
+<span class="fc" id="L1159"> notFull.signalAll();</span>
+ } finally {
+<span class="fc" id="L1161"> lock.unlock();</span>
+ }
+<span class="fc" id="L1163"> }</span>
+
+ /**
+ * Returns an iterator over the elements in this deque in proper sequence.
+ * The elements will be returned in order from first (head) to last (tail).
+ * The returned {@code Iterator} is a "weakly consistent" iterator that
+ * will never throw {@link java.util.ConcurrentModificationException
+ * ConcurrentModificationException},
+ * and guarantees to traverse elements as they existed upon
+ * construction of the iterator, and may (but is not guaranteed to)
+ * reflect any modifications subsequent to construction.
+ *
+ * @return an iterator over the elements in this deque in proper sequence
+ */
+ @Override
+ public Iterator<E> iterator() {
+<span class="fc" id="L1179"> return new Itr();</span>
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Iterator<E> descendingIterator() {
+<span class="fc" id="L1187"> return new DescendingItr();</span>
+ }
+
+ /**
+ * Base class for Iterators for LinkedBlockingDeque
+ */
+ private abstract class AbstractItr implements Iterator<E> {
+ /**
+ * The next node to return in next()
+ */
+ Node<E> next;
+
+ /**
+ * nextItem holds on to item fields because once we claim that
+ * an element exists in hasNext(), we must return item read
+ * under lock (in advance()) even if it was in the process of
+ * being removed when hasNext() was called.
+ */
+ E nextItem;
+
+ /**
+ * Node returned by most recent call to next. Needed by remove.
+ * Reset to null if this element is deleted by a call to remove.
+ */
+ private Node<E> lastRet;
+
+ /**
+ * Obtain the first node to be returned by the iterator.
+ *
+ * @return first node
+ */
+ abstract Node<E> firstNode();
+
+ /**
+ * For a given node, obtain the next node to be returned by the
+ * iterator.
+ *
+ * @param n given node
+ *
+ * @return next node
+ */
+ abstract Node<E> nextNode(Node<E> n);
+
+ /**
+ * Create a new iterator. Sets the initial position.
+ */
+<span class="fc" id="L1233"> AbstractItr() {</span>
+ // set to initial position
+<span class="fc" id="L1235"> lock.lock();</span>
+ try {
+<span class="fc" id="L1237"> next = firstNode();</span>
+<span class="fc bfc" id="L1238" title="All 2 branches covered."> nextItem = next == null ? null : next.item;</span>
+ } finally {
+<span class="fc" id="L1240"> lock.unlock();</span>
+ }
+<span class="fc" id="L1242"> }</span>
+
+ /**
+ * Returns the successor node of the given non-null, but
+ * possibly previously deleted, node.
+ *
+ * @param n node whose successor is sought
+ * @return successor node
+ */
+ private Node<E> succ(Node<E> n) {
+ // Chains of deleted nodes ending in null or self-links
+ // are possible if multiple interior nodes are removed.
+ for (;;) {
+<span class="fc" id="L1255"> final Node<E> s = nextNode(n);</span>
+<span class="fc bfc" id="L1256" title="All 2 branches covered."> if (s == null) {</span>
+<span class="fc" id="L1257"> return null;</span>
+<span class="fc bfc" id="L1258" title="All 2 branches covered."> } else if (s.item != null) {</span>
+<span class="fc" id="L1259"> return s;</span>
+<span class="fc bfc" id="L1260" title="All 2 branches covered."> } else if (s == n) {</span>
+<span class="fc" id="L1261"> return firstNode();</span>
+ } else {
+<span class="fc" id="L1263"> n = s;</span>
+ }
+<span class="fc" id="L1265"> }</span>
+ }
+
+ /**
+ * Advances next.
+ */
+ void advance() {
+<span class="fc" id="L1272"> lock.lock();</span>
+ try {
+ // assert next != null;
+<span class="fc" id="L1275"> next = succ(next);</span>
+<span class="fc bfc" id="L1276" title="All 2 branches covered."> nextItem = next == null ? null : next.item;</span>
+ } finally {
+<span class="fc" id="L1278"> lock.unlock();</span>
+ }
+<span class="fc" id="L1280"> }</span>
+
+ @Override
+ public boolean hasNext() {
+<span class="fc bfc" id="L1284" title="All 2 branches covered."> return next != null;</span>
+ }
+
+ @Override
+ public E next() {
+<span class="fc bfc" id="L1289" title="All 2 branches covered."> if (next == null) {</span>
+<span class="fc" id="L1290"> throw new NoSuchElementException();</span>
+ }
+<span class="fc" id="L1292"> lastRet = next;</span>
+<span class="fc" id="L1293"> final E x = nextItem;</span>
+<span class="fc" id="L1294"> advance();</span>
+<span class="fc" id="L1295"> return x;</span>
+ }
+
+ @Override
+ public void remove() {
+<span class="fc" id="L1300"> final Node<E> n = lastRet;</span>
+<span class="pc bpc" id="L1301" title="1 of 2 branches missed."> if (n == null) {</span>
+<span class="nc" id="L1302"> throw new IllegalStateException();</span>
+ }
+<span class="fc" id="L1304"> lastRet = null;</span>
+<span class="fc" id="L1305"> lock.lock();</span>
+ try {
+<span class="pc bpc" id="L1307" title="1 of 2 branches missed."> if (n.item != null) {</span>
+<span class="fc" id="L1308"> unlink(n);</span>
+ }
+ } finally {
+<span class="fc" id="L1311"> lock.unlock();</span>
+ }
+<span class="fc" id="L1313"> }</span>
+ }
+
+ /** Forward iterator */
+<span class="fc" id="L1317"> private class Itr extends AbstractItr {</span>
+ @Override
+<span class="fc" id="L1319"> Node<E> firstNode() { return first; }</span>
+ @Override
+<span class="fc" id="L1321"> Node<E> nextNode(final Node<E> n) { return n.next; }</span>
+ }
+
+ /** Descending iterator */
+<span class="fc" id="L1325"> private class DescendingItr extends AbstractItr {</span>
+ @Override
+<span class="fc" id="L1327"> Node<E> firstNode() { return last; }</span>
+ @Override
+<span class="fc" id="L1329"> Node<E> nextNode(final Node<E> n) { return n.prev; }</span>
+ }
+
+ /**
+ * Saves the state of this deque to a stream (that is, serialize it).
+ *
+ * @serialData The capacity (int), followed by elements (each an
+ * {@code Object}) in the proper order, followed by a null
+ * @param s the stream
+ */
+ private void writeObject(final java.io.ObjectOutputStream s)
+ throws java.io.IOException {
+<span class="nc" id="L1341"> lock.lock();</span>
+ try {
+ // Write out capacity and any hidden stuff
+<span class="nc" id="L1344"> s.defaultWriteObject();</span>
+ // Write out all elements in the proper order.
+<span class="nc bnc" id="L1346" title="All 2 branches missed."> for (Node<E> p = first; p != null; p = p.next) {</span>
+<span class="nc" id="L1347"> s.writeObject(p.item);</span>
+ }
+ // Use trailing null as sentinel
+<span class="nc" id="L1350"> s.writeObject(null);</span>
+ } finally {
+<span class="nc" id="L1352"> lock.unlock();</span>
+ }
+<span class="nc" id="L1354"> }</span>
+
+ /**
+ * Reconstitutes this deque from a stream (that is,
+ * deserialize it).
+ * @param s the stream
+ */
+ private void readObject(final java.io.ObjectInputStream s)
+ throws java.io.IOException, ClassNotFoundException {
+<span class="nc" id="L1363"> s.defaultReadObject();</span>
+<span class="nc" id="L1364"> count = 0;</span>
+<span class="nc" id="L1365"> first = null;</span>
+<span class="nc" id="L1366"> last = null;</span>
+ // Read in all elements and place in queue
+ for (;;) {
+ @SuppressWarnings("unchecked")
+ final
+<span class="nc" id="L1371"> E item = (E)s.readObject();</span>
+<span class="nc bnc" id="L1372" title="All 2 branches missed."> if (item == null) {</span>
+<span class="nc" id="L1373"> break;</span>
+ }
+<span class="nc" id="L1375"> add(item);</span>
+<span class="nc" id="L1376"> }</span>
+<span class="nc" id="L1377"> }</span>
+
+ // Monitoring methods
+
+ /**
+ * Returns true if there are threads waiting to take instances from this deque. See disclaimer on accuracy in
+ * {@link java.util.concurrent.locks.ReentrantLock#hasWaiters(Condition)}.
+ *
+ * @return true if there is at least one thread waiting on this deque's notEmpty condition.
+ */
+ public boolean hasTakeWaiters() {
+<span class="fc" id="L1388"> lock.lock();</span>
+ try {
+<span class="fc" id="L1390"> return lock.hasWaiters(notEmpty);</span>
+ } finally {
+<span class="fc" id="L1392"> lock.unlock();</span>
+ }
+ }
+
+ /**
+ * Returns the length of the queue of threads waiting to take instances from this deque. See disclaimer on accuracy
+ * in {@link java.util.concurrent.locks.ReentrantLock#getWaitQueueLength(Condition)}.
+ *
+ * @return number of threads waiting on this deque's notEmpty condition.
+ */
+ public int getTakeQueueLength() {
+<span class="fc" id="L1403"> lock.lock();</span>
+ try {
+<span class="fc" id="L1405"> return lock.getWaitQueueLength(notEmpty);</span>
+ } finally {
+<span class="fc" id="L1407"> lock.unlock();</span>
+ }
+ }
+
+ /**
+ * Interrupts the threads currently waiting to take an object from the pool. See disclaimer on accuracy in
+ * {@link java.util.concurrent.locks.ReentrantLock#getWaitingThreads(Condition)}.
+ */
+ public void interuptTakeWaiters() {
+<span class="fc" id="L1416"> lock.lock();</span>
+ try {
+<span class="fc" id="L1418"> lock.interruptWaiters(notEmpty);</span>
+ } finally {
+<span class="fc" id="L1420"> lock.unlock();</span>
+ }
+<span class="fc" id="L1422"> }</span>
+}
+</pre><div class="footer"><span class="right">Created with <a href="http://www.jacoco.org/jacoco">JaCoCo</a> 0.8.3.201901230119</span></div></body></html>
\ No newline at end of file
Added: websites/production/commons/content/proper/commons-pool/jacoco/org.apache.commons.pool2.impl/NoOpCallStack.html
==============================================================================
--- websites/production/commons/content/proper/commons-pool/jacoco/org.apache.commons.pool2.impl/NoOpCallStack.html (added)
+++ websites/production/commons/content/proper/commons-pool/jacoco/org.apache.commons.pool2.impl/NoOpCallStack.html Sat Aug 10 22:26:44 2019
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en"><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/><link rel="stylesheet" href="../jacoco-resources/report.css" type="text/css"/><link rel="shortcut icon" href="../jacoco-resources/report.gif" type="image/gif"/><title>NoOpCallStack</title><script type="text/javascript" src="../jacoco-resources/sort.js"></script></head><body onload="initialSort(['breadcrumb'])"><div class="breadcrumb" id="breadcrumb"><span class="info"><a href="../jacoco-sessions.html" class="el_session">Sessions</a></span><a href="../index.html" class="el_report">Apache Commons Pool</a> > <a href="index.html" class="el_package">org.apache.commons.pool2.impl</a> > <span class="el_class">NoOpCallStack</span></div><h1>NoOpCallStack</h1><table class="coverage" cellspacing="0" id="coveragetable"><
thead><tr><td class="sortable" id="a" onclick="toggleSort(this)">Element</td><td class="down sortable bar" id="b" onclick="toggleSort(this)">Missed Instructions</td><td class="sortable ctr2" id="c" onclick="toggleSort(this)">Cov.</td><td class="sortable bar" id="d" onclick="toggleSort(this)">Missed Branches</td><td class="sortable ctr2" id="e" onclick="toggleSort(this)">Cov.</td><td class="sortable ctr1" id="f" onclick="toggleSort(this)">Missed</td><td class="sortable ctr2" id="g" onclick="toggleSort(this)">Cxty</td><td class="sortable ctr1" id="h" onclick="toggleSort(this)">Missed</td><td class="sortable ctr2" id="i" onclick="toggleSort(this)">Lines</td><td class="sortable ctr1" id="j" onclick="toggleSort(this)">Missed</td><td class="sortable ctr2" id="k" onclick="toggleSort(this)">Methods</td></tr></thead><tfoot><tr><td>Total</td><td class="bar">3 of 9</td><td class="ctr2">66%</td><td class="bar">0 of 0</td><td class="ctr2">n/a</td><td class="ctr1">2</td><td class="ctr2">4</td><td
class="ctr1">2</td><td class="ctr2">4</td><td class="ctr1">2</td><td class="ctr2">4</td></tr></tfoot><tbody><tr><td id="a2"><a href="NoOpCallStack.java.html#L42" class="el_method">printStackTrace(PrintWriter)</a></td><td class="bar" id="b0"><img src="../jacoco-resources/redbar.gif" width="48" height="10" title="2" alt="2"/></td><td class="ctr2" id="c2">0%</td><td class="bar" id="d0"/><td class="ctr2" id="e0">n/a</td><td class="ctr1" id="f0">1</td><td class="ctr2" id="g0">1</td><td class="ctr1" id="h0">1</td><td class="ctr2" id="i0">1</td><td class="ctr1" id="j0">1</td><td class="ctr2" id="k0">1</td></tr><tr><td id="a1"><a href="NoOpCallStack.java.html#L48" class="el_method">fillInStackTrace()</a></td><td class="bar" id="b1"><img src="../jacoco-resources/redbar.gif" width="24" height="10" title="1" alt="1"/></td><td class="ctr2" id="c3">0%</td><td class="bar" id="d1"/><td class="ctr2" id="e1">n/a</td><td class="ctr1" id="f1">1</td><td class="ctr2" id="g1">1</td><td class="ctr1" id="
h1">1</td><td class="ctr2" id="i1">1</td><td class="ctr1" id="j1">1</td><td class="ctr2" id="k1">1</td></tr><tr><td id="a3"><a href="NoOpCallStack.java.html#L32" class="el_method">static {...}</a></td><td class="bar" id="b2"><img src="../jacoco-resources/greenbar.gif" width="120" height="10" title="5" alt="5"/></td><td class="ctr2" id="c0">100%</td><td class="bar" id="d2"/><td class="ctr2" id="e2">n/a</td><td class="ctr1" id="f2">0</td><td class="ctr2" id="g2">1</td><td class="ctr1" id="h2">0</td><td class="ctr2" id="i2">1</td><td class="ctr1" id="j2">0</td><td class="ctr2" id="k2">1</td></tr><tr><td id="a0"><a href="NoOpCallStack.java.html#L53" class="el_method">clear()</a></td><td class="bar" id="b3"><img src="../jacoco-resources/greenbar.gif" width="24" height="10" title="1" alt="1"/></td><td class="ctr2" id="c1">100%</td><td class="bar" id="d3"/><td class="ctr2" id="e3">n/a</td><td class="ctr1" id="f3">0</td><td class="ctr2" id="g3">1</td><td class="ctr1" id="h3">0</td><td class
="ctr2" id="i3">1</td><td class="ctr1" id="j3">0</td><td class="ctr2" id="k3">1</td></tr></tbody></table><div class="footer"><span class="right">Created with <a href="http://www.jacoco.org/jacoco">JaCoCo</a> 0.8.3.201901230119</span></div></body></html>
\ No newline at end of file
Added: websites/production/commons/content/proper/commons-pool/jacoco/org.apache.commons.pool2.impl/NoOpCallStack.java.html
==============================================================================
--- websites/production/commons/content/proper/commons-pool/jacoco/org.apache.commons.pool2.impl/NoOpCallStack.java.html (added)
+++ websites/production/commons/content/proper/commons-pool/jacoco/org.apache.commons.pool2.impl/NoOpCallStack.java.html Sat Aug 10 22:26:44 2019
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en"><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/><link rel="stylesheet" href="../jacoco-resources/report.css" type="text/css"/><link rel="shortcut icon" href="../jacoco-resources/report.gif" type="image/gif"/><title>NoOpCallStack.java</title><link rel="stylesheet" href="../jacoco-resources/prettify.css" type="text/css"/><script type="text/javascript" src="../jacoco-resources/prettify.js"></script></head><body onload="window['PR_TAB_WIDTH']=4;prettyPrint()"><div class="breadcrumb" id="breadcrumb"><span class="info"><a href="../jacoco-sessions.html" class="el_session">Sessions</a></span><a href="../index.html" class="el_report">Apache Commons Pool</a> > <a href="index.source.html" class="el_package">org.apache.commons.pool2.impl</a> > <span class="el_source">
NoOpCallStack.java</span></div><h1>NoOpCallStack.java</h1><pre class="source lang-java linenums">/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.pool2.impl;
+
+import java.io.PrintWriter;
+
+/**
+ * CallStack strategy using no-op implementations of all functionality. Can be used by default when abandoned object
+ * logging is disabled.
+ *
+ * @since 2.5
+ */
+public class NoOpCallStack implements CallStack {
+
+ /**
+ * Singleton instance.
+ */
+<span class="fc" id="L32"> public static final CallStack INSTANCE = new NoOpCallStack();</span>
+
+ /**
+ * Constructs the singleton instance.
+ */
+ private NoOpCallStack() {
+ }
+
+ @Override
+ public boolean printStackTrace(final PrintWriter writer) {
+<span class="nc" id="L42"> return false;</span>
+ }
+
+ @Override
+ public void fillInStackTrace() {
+ // no-op
+<span class="nc" id="L48"> }</span>
+
+ @Override
+ public void clear() {
+ // no-op
+<span class="fc" id="L53"> }</span>
+}
+</pre><div class="footer"><span class="right">Created with <a href="http://www.jacoco.org/jacoco">JaCoCo</a> 0.8.3.201901230119</span></div></body></html>
\ No newline at end of file
Added: websites/production/commons/content/proper/commons-pool/jacoco/org.apache.commons.pool2.impl/PoolImplUtils.html
==============================================================================
--- websites/production/commons/content/proper/commons-pool/jacoco/org.apache.commons.pool2.impl/PoolImplUtils.html (added)
+++ websites/production/commons/content/proper/commons-pool/jacoco/org.apache.commons.pool2.impl/PoolImplUtils.html Sat Aug 10 22:26:44 2019
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en"><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/><link rel="stylesheet" href="../jacoco-resources/report.css" type="text/css"/><link rel="shortcut icon" href="../jacoco-resources/report.gif" type="image/gif"/><title>PoolImplUtils</title><script type="text/javascript" src="../jacoco-resources/sort.js"></script></head><body onload="initialSort(['breadcrumb'])"><div class="breadcrumb" id="breadcrumb"><span class="info"><a href="../jacoco-sessions.html" class="el_session">Sessions</a></span><a href="../index.html" class="el_report">Apache Commons Pool</a> > <a href="index.html" class="el_package">org.apache.commons.pool2.impl</a> > <span class="el_class">PoolImplUtils</span></div><h1>PoolImplUtils</h1><table class="coverage" cellspacing="0" id="coveragetable"><
thead><tr><td class="sortable" id="a" onclick="toggleSort(this)">Element</td><td class="down sortable bar" id="b" onclick="toggleSort(this)">Missed Instructions</td><td class="sortable ctr2" id="c" onclick="toggleSort(this)">Cov.</td><td class="sortable bar" id="d" onclick="toggleSort(this)">Missed Branches</td><td class="sortable ctr2" id="e" onclick="toggleSort(this)">Cov.</td><td class="sortable ctr1" id="f" onclick="toggleSort(this)">Missed</td><td class="sortable ctr2" id="g" onclick="toggleSort(this)">Cxty</td><td class="sortable ctr1" id="h" onclick="toggleSort(this)">Missed</td><td class="sortable ctr2" id="i" onclick="toggleSort(this)">Lines</td><td class="sortable ctr1" id="j" onclick="toggleSort(this)">Missed</td><td class="sortable ctr2" id="k" onclick="toggleSort(this)">Methods</td></tr></thead><tfoot><tr><td>Total</td><td class="bar">13 of 160</td><td class="ctr2">91%</td><td class="bar">11 of 34</td><td class="ctr2">67%</td><td class="ctr1">12</td><td class="ctr2">22<
/td><td class="ctr1">5</td><td class="ctr2">39</td><td class="ctr1">1</td><td class="ctr2">5</td></tr></tfoot><tbody><tr><td id="a1"><a href="PoolImplUtils.java.html#L78" class="el_method">getGenericType(Class, Class)</a></td><td class="bar" id="b0"><img src="../jacoco-resources/redbar.gif" width="9" height="10" title="4" alt="4"/><img src="../jacoco-resources/greenbar.gif" width="110" height="10" title="45" alt="45"/></td><td class="ctr2" id="c3">91%</td><td class="bar" id="d1"><img src="../jacoco-resources/redbar.gif" width="36" height="10" title="3" alt="3"/><img src="../jacoco-resources/greenbar.gif" width="84" height="10" title="7" alt="7"/></td><td class="ctr2" id="e1">70%</td><td class="ctr1" id="f1">3</td><td class="ctr2" id="g0">6</td><td class="ctr1" id="h0">2</td><td class="ctr2" id="i0">13</td><td class="ctr1" id="j1">0</td><td class="ctr2" id="k0">1</td></tr><tr><td id="a4"><a href="PoolImplUtils.java.html#L30" class="el_method">PoolImplUtils()</a></td><td class="bar" i
d="b1"><img src="../jacoco-resources/redbar.gif" width="7" height="10" title="3" alt="3"/></td><td class="ctr2" id="c4">0%</td><td class="bar" id="d4"/><td class="ctr2" id="e4">n/a</td><td class="ctr1" id="f3">1</td><td class="ctr2" id="g4">1</td><td class="ctr1" id="h1">1</td><td class="ctr2" id="i4">1</td><td class="ctr1" id="j0">1</td><td class="ctr2" id="k1">1</td></tr><tr><td id="a0"><a href="PoolImplUtils.java.html#L42" class="el_method">getFactoryType(Class)</a></td><td class="bar" id="b2"><img src="../jacoco-resources/redbar.gif" width="4" height="10" title="2" alt="2"/><img src="../jacoco-resources/greenbar.gif" width="102" height="10" title="42" alt="42"/></td><td class="ctr2" id="c0">95%</td><td class="bar" id="d0"><img src="../jacoco-resources/redbar.gif" width="48" height="10" title="4" alt="4"/><img src="../jacoco-resources/greenbar.gif" width="72" height="10" title="6" alt="6"/></td><td class="ctr2" id="e3">60%</td><td class="ctr1" id="f0">4</td><td class="ctr2" id="g
1">6</td><td class="ctr1" id="h2">1</td><td class="ctr2" id="i1">12</td><td class="ctr1" id="j2">0</td><td class="ctr2" id="k2">1</td></tr><tr><td id="a2"><a href="PoolImplUtils.java.html#L119" class="el_method">getParameterizedType(Class, Class)</a></td><td class="bar" id="b3"><img src="../jacoco-resources/redbar.gif" width="4" height="10" title="2" alt="2"/><img src="../jacoco-resources/greenbar.gif" width="85" height="10" title="35" alt="35"/></td><td class="ctr2" id="c1">94%</td><td class="bar" id="d2"><img src="../jacoco-resources/redbar.gif" width="36" height="10" title="3" alt="3"/><img src="../jacoco-resources/greenbar.gif" width="60" height="10" title="5" alt="5"/></td><td class="ctr2" id="e2">62%</td><td class="ctr1" id="f2">3</td><td class="ctr2" id="g2">5</td><td class="ctr1" id="h4">0</td><td class="ctr2" id="i3">6</td><td class="ctr1" id="j3">0</td><td class="ctr2" id="k3">1</td></tr><tr><td id="a3"><a href="PoolImplUtils.java.html#L145" class="el_method">getTypeParame
ter(Class, Type)</a></td><td class="bar" id="b4"><img src="../jacoco-resources/redbar.gif" width="4" height="10" title="2" alt="2"/><img src="../jacoco-resources/greenbar.gif" width="61" height="10" title="25" alt="25"/></td><td class="ctr2" id="c2">92%</td><td class="bar" id="d3"><img src="../jacoco-resources/redbar.gif" width="12" height="10" title="1" alt="1"/><img src="../jacoco-resources/greenbar.gif" width="60" height="10" title="5" alt="5"/></td><td class="ctr2" id="e0">83%</td><td class="ctr1" id="f4">1</td><td class="ctr2" id="g3">4</td><td class="ctr1" id="h3">1</td><td class="ctr2" id="i2">7</td><td class="ctr1" id="j4">0</td><td class="ctr2" id="k4">1</td></tr></tbody></table><div class="footer"><span class="right">Created with <a href="http://www.jacoco.org/jacoco">JaCoCo</a> 0.8.3.201901230119</span></div></body></html>
\ No newline at end of file
Added: websites/production/commons/content/proper/commons-pool/jacoco/org.apache.commons.pool2.impl/PoolImplUtils.java.html
==============================================================================
--- websites/production/commons/content/proper/commons-pool/jacoco/org.apache.commons.pool2.impl/PoolImplUtils.java.html (added)
+++ websites/production/commons/content/proper/commons-pool/jacoco/org.apache.commons.pool2.impl/PoolImplUtils.java.html Sat Aug 10 22:26:44 2019
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en"><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/><link rel="stylesheet" href="../jacoco-resources/report.css" type="text/css"/><link rel="shortcut icon" href="../jacoco-resources/report.gif" type="image/gif"/><title>PoolImplUtils.java</title><link rel="stylesheet" href="../jacoco-resources/prettify.css" type="text/css"/><script type="text/javascript" src="../jacoco-resources/prettify.js"></script></head><body onload="window['PR_TAB_WIDTH']=4;prettyPrint()"><div class="breadcrumb" id="breadcrumb"><span class="info"><a href="../jacoco-sessions.html" class="el_session">Sessions</a></span><a href="../index.html" class="el_report">Apache Commons Pool</a> > <a href="index.source.html" class="el_package">org.apache.commons.pool2.impl</a> > <span class="el_source">
PoolImplUtils.java</span></div><h1>PoolImplUtils.java</h1><pre class="source lang-java linenums">/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.pool2.impl;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+
+import org.apache.commons.pool2.PooledObjectFactory;
+
+/**
+ * Implementation specific utilities.
+ *
+ * @since 2.0
+ */
+<span class="nc" id="L30">class PoolImplUtils {</span>
+
+ /**
+ * Identifies the concrete type of object that an object factory creates.
+ *
+ * @param factoryClass
+ * The factory to examine
+ *
+ * @return the type of object the factory creates
+ */
+ @SuppressWarnings("rawtypes")
+ static Class<?> getFactoryType(final Class<? extends PooledObjectFactory> factoryClass) {
+<span class="fc" id="L42"> final Class<PooledObjectFactory> type = PooledObjectFactory.class;</span>
+<span class="fc" id="L43"> final Object genericType = getGenericType(type, factoryClass);</span>
+<span class="fc bfc" id="L44" title="All 2 branches covered."> if (genericType instanceof Integer) {</span>
+ // POOL-324 org.apache.commons.pool2.impl.GenericObjectPool.getFactoryType() throws
+ // java.lang.ClassCastException
+ //
+ // A bit hackish, but we must handle cases when getGenericType() does not return a concrete types.
+<span class="fc" id="L49"> final ParameterizedType pi = getParameterizedType(type, factoryClass);</span>
+<span class="pc bpc" id="L50" title="1 of 2 branches missed."> if (pi != null) {</span>
+<span class="fc" id="L51"> final Type[] bounds = ((TypeVariable) pi.getActualTypeArguments()[(Integer) genericType]).getBounds();</span>
+<span class="pc bpc" id="L52" title="2 of 4 branches missed."> if (bounds != null && bounds.length > 0) {</span>
+<span class="fc" id="L53"> final Type bound0 = bounds[0];</span>
+<span class="pc bpc" id="L54" title="1 of 2 branches missed."> if (bound0 instanceof Class) {</span>
+<span class="fc" id="L55"> return (Class<?>) bound0;</span>
+ }
+ }
+ }
+ // last resort: Always return a Class
+<span class="nc" id="L60"> return Object.class;</span>
+ }
+<span class="fc" id="L62"> return (Class<?>) genericType;</span>
+ }
+
+ /**
+ * Obtains the concrete type used by an implementation of an interface that uses a generic type.
+ *
+ * @param type
+ * The interface that defines a generic type
+ * @param clazz
+ * The class that implements the interface with a concrete type
+ * @param <T>
+ * The interface type
+ *
+ * @return concrete type used by the implementation
+ */
+ private static <T> Object getGenericType(final Class<T> type, final Class<? extends T> clazz) {
+<span class="pc bpc" id="L78" title="2 of 4 branches missed."> if (type == null || clazz == null) {</span>
+ // Error will be logged further up the call stack
+<span class="nc" id="L80"> return null;</span>
+ }
+
+ // Look to see if this class implements the generic interface
+<span class="fc" id="L84"> final ParameterizedType pi = getParameterizedType(type, clazz);</span>
+<span class="fc bfc" id="L85" title="All 2 branches covered."> if (pi != null) {</span>
+<span class="fc" id="L86"> return getTypeParameter(clazz, pi.getActualTypeArguments()[0]);</span>
+ }
+
+ // Interface not found on this class. Look at the superclass.
+ @SuppressWarnings("unchecked")
+<span class="fc" id="L91"> final Class<? extends T> superClass = (Class<? extends T>) clazz.getSuperclass();</span>
+
+<span class="fc" id="L93"> final Object result = getGenericType(type, superClass);</span>
+<span class="fc bfc" id="L94" title="All 2 branches covered."> if (result instanceof Class<?>) {</span>
+ // Superclass implements interface and defines explicit type for generic
+<span class="fc" id="L96"> return result;</span>
+<span class="pc bpc" id="L97" title="1 of 2 branches missed."> } else if (result instanceof Integer) {</span>
+ // Superclass implements interface and defines unknown type for generic
+ // Map that unknown type to the generic types defined in this class
+<span class="fc" id="L100"> final ParameterizedType superClassType = (ParameterizedType) clazz.getGenericSuperclass();</span>
+<span class="fc" id="L101"> return getTypeParameter(clazz, superClassType.getActualTypeArguments()[((Integer) result).intValue()]);</span>
+ } else {
+ // Error will be logged further up the call stack
+<span class="nc" id="L104"> return null;</span>
+ }
+ }
+
+ /**
+ * Gets the matching parameterized type or null.
+ * @param type
+ * The interface that defines a generic type.
+ * @param clazz
+ * The class that implements the interface with a concrete type.
+ * @param <T>
+ * The interface type.
+ * @return the matching parameterized type or null.
+ */
+ private static <T> ParameterizedType getParameterizedType(final Class<T> type, final Class<? extends T> clazz) {
+<span class="pc bfc" id="L119" title="All 2 branches covered."> for (final Type iface : clazz.getGenericInterfaces()) {</span>
+ // Only need to check interfaces that use generics
+<span class="pc bpc" id="L121" title="1 of 2 branches missed."> if (iface instanceof ParameterizedType) {</span>
+<span class="fc" id="L122"> final ParameterizedType pi = (ParameterizedType) iface;</span>
+ // Look for the generic interface
+<span class="pc bpc" id="L124" title="2 of 4 branches missed."> if (pi.getRawType() instanceof Class && type.isAssignableFrom((Class<?>) pi.getRawType())) {</span>
+<span class="fc" id="L125"> return pi;</span>
+ }
+ }
+ }
+<span class="fc" id="L129"> return null;</span>
+ }
+
+ /**
+ * For a generic parameter, return either the Class used or if the type is unknown, the index for the type in
+ * definition of the class
+ *
+ * @param clazz
+ * defining class
+ * @param argType
+ * the type argument of interest
+ *
+ * @return An instance of {@link Class} representing the type used by the type parameter or an instance of
+ * {@link Integer} representing the index for the type in the definition of the defining class
+ */
+ private static Object getTypeParameter(final Class<?> clazz, final Type argType) {
+<span class="fc bfc" id="L145" title="All 2 branches covered."> if (argType instanceof Class<?>) {</span>
+<span class="fc" id="L146"> return argType;</span>
+ }
+<span class="fc" id="L148"> final TypeVariable<?>[] tvs = clazz.getTypeParameters();</span>
+<span class="pc bpc" id="L149" title="1 of 2 branches missed."> for (int i = 0; i < tvs.length; i++) {</span>
+<span class="fc bfc" id="L150" title="All 2 branches covered."> if (tvs[i].equals(argType)) {</span>
+<span class="fc" id="L151"> return Integer.valueOf(i);</span>
+ }
+ }
+<span class="nc" id="L154"> return null;</span>
+ }
+}
+</pre><div class="footer"><span class="right">Created with <a href="http://www.jacoco.org/jacoco">JaCoCo</a> 0.8.3.201901230119</span></div></body></html>
\ No newline at end of file