001    /*
002     * Copyright (C) 2011 The Guava Authors
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
005     * in compliance with the License. You may obtain a copy of the License at
006     *
007     * http://www.apache.org/licenses/LICENSE-2.0
008     *
009     * Unless required by applicable law or agreed to in writing, software distributed under the License
010     * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
011     * or implied. See the License for the specific language governing permissions and limitations under
012     * the License.
013     */
014    
015    package com.google.common.collect;
016    
017    import com.google.common.annotations.Beta;
018    import com.google.common.base.Preconditions;
019    
020    import java.util.Collection;
021    import java.util.PriorityQueue;
022    import java.util.Queue;
023    import java.util.concurrent.ArrayBlockingQueue;
024    import java.util.concurrent.BlockingQueue;
025    import java.util.concurrent.ConcurrentLinkedQueue;
026    import java.util.concurrent.LinkedBlockingQueue;
027    import java.util.concurrent.PriorityBlockingQueue;
028    import java.util.concurrent.SynchronousQueue;
029    import java.util.concurrent.TimeUnit;
030    
031    /**
032     * Static utility methods pertaining to {@link Queue} and {@link Deque} instances.
033     * Also see this class's counterparts {@link Lists}, {@link Sets}, and {@link Maps}.
034     *
035     * @author Kurt Alfred Kluever
036     * @since 11.0
037     */
038    @Beta
039    public final class Queues {
040      private Queues() {}
041    
042      // ArrayBlockingQueue
043    
044      /**
045       * Creates an empty {@code ArrayBlockingQueue} instance.
046       *
047       * @return a new, empty {@code ArrayBlockingQueue}
048       */
049      public static <E> ArrayBlockingQueue<E> newArrayBlockingQueue(int capacity) {
050        return new ArrayBlockingQueue<E>(capacity);
051      }
052    
053      // ConcurrentLinkedQueue
054    
055      /**
056       * Creates an empty {@code ConcurrentLinkedQueue} instance.
057       *
058       * @return a new, empty {@code ConcurrentLinkedQueue}
059       */
060      public static <E> ConcurrentLinkedQueue<E> newConcurrentLinkedQueue() {
061        return new ConcurrentLinkedQueue<E>();
062      }
063    
064      /**
065       * Creates an {@code ConcurrentLinkedQueue} instance containing the given elements.
066       *
067       * @param elements the elements that the queue should contain, in order
068       * @return a new {@code ConcurrentLinkedQueue} containing those elements
069       */
070      public static <E> ConcurrentLinkedQueue<E> newConcurrentLinkedQueue(
071          Iterable<? extends E> elements) {
072        if (elements instanceof Collection) {
073          return new ConcurrentLinkedQueue<E>(Collections2.cast(elements));
074        }
075        ConcurrentLinkedQueue<E> queue = new ConcurrentLinkedQueue<E>();
076        Iterables.addAll(queue, elements);
077        return queue;
078      }
079    
080      // LinkedBlockingQueue
081    
082      /**
083       * Creates an empty {@code LinkedBlockingQueue} instance.
084       *
085       * @return a new, empty {@code LinkedBlockingQueue}
086       */
087      public static <E> LinkedBlockingQueue<E> newLinkedBlockingQueue() {
088        return new LinkedBlockingQueue<E>();
089      }
090    
091      /**
092       * Creates a {@code LinkedBlockingQueue} with the given (fixed) capacity.
093       *
094       * @param capacity the capacity of this queue
095       * @return a new, empty {@code LinkedBlockingQueue}
096       * @throws IllegalArgumentException if {@code capacity} is less than 1
097       */
098      public static <E> LinkedBlockingQueue<E> newLinkedBlockingQueue(int capacity) {
099        return new LinkedBlockingQueue<E>(capacity);
100      }
101    
102      /**
103       * Creates an {@code LinkedBlockingQueue} instance containing the given elements.
104       *
105       * @param elements the elements that the queue should contain, in order
106       * @return a new {@code LinkedBlockingQueue} containing those elements
107       */
108      public static <E> LinkedBlockingQueue<E> newLinkedBlockingQueue(Iterable<? extends E> elements) {
109        if (elements instanceof Collection) {
110          return new LinkedBlockingQueue<E>(Collections2.cast(elements));
111        }
112        LinkedBlockingQueue<E> queue = new LinkedBlockingQueue<E>();
113        Iterables.addAll(queue, elements);
114        return queue;
115      }
116    
117      // LinkedList: see {@link com.google.common.collect.Lists}
118    
119      // PriorityBlockingQueue
120    
121      /**
122       * Creates an empty {@code PriorityBlockingQueue} instance.
123       *
124       * @return a new, empty {@code PriorityBlockingQueue}
125       */
126      public static <E> PriorityBlockingQueue<E> newPriorityBlockingQueue() {
127        return new PriorityBlockingQueue<E>();
128      }
129    
130      /**
131       * Creates an {@code PriorityBlockingQueue} instance containing the given elements.
132       *
133       * @param elements the elements that the queue should contain, in order
134       * @return a new {@code PriorityBlockingQueue} containing those elements
135       */
136      public static <E> PriorityBlockingQueue<E> newPriorityBlockingQueue(
137          Iterable<? extends E> elements) {
138        if (elements instanceof Collection) {
139          return new PriorityBlockingQueue<E>(Collections2.cast(elements));
140        }
141        PriorityBlockingQueue<E> queue = new PriorityBlockingQueue<E>();
142        Iterables.addAll(queue, elements);
143        return queue;
144      }
145    
146      // PriorityQueue
147    
148      /**
149       * Creates an empty {@code PriorityQueue} instance.
150       *
151       * @return a new, empty {@code PriorityQueue}
152       */
153      public static <E> PriorityQueue<E> newPriorityQueue() {
154        return new PriorityQueue<E>();
155      }
156    
157      /**
158       * Creates an {@code PriorityQueue} instance containing the given elements.
159       *
160       * @param elements the elements that the queue should contain, in order
161       * @return a new {@code PriorityQueue} containing those elements
162       */
163      public static <E> PriorityQueue<E> newPriorityQueue(Iterable<? extends E> elements) {
164        if (elements instanceof Collection) {
165          return new PriorityQueue<E>(Collections2.cast(elements));
166        }
167        PriorityQueue<E> queue = new PriorityQueue<E>();
168        Iterables.addAll(queue, elements);
169        return queue;
170      }
171    
172      // SynchronousQueue
173    
174      /**
175       * Creates an empty {@code SynchronousQueue} instance.
176       *
177       * @return a new, empty {@code SynchronousQueue}
178       */
179      public static <E> SynchronousQueue<E> newSynchronousQueue() {
180        return new SynchronousQueue<E>();
181      }
182      
183      /**
184       * Drains the queue as {@link BlockingQueue#drainTo(Collection, int)}, but if the requested 
185       * {@code numElements} elements are not available, it will wait for them up to the specified
186       * timeout.
187       * 
188       * @param q the blocking queue to be drained
189       * @param buffer where to add the transferred elements
190       * @param numElements the number of elements to be waited for
191       * @param timeout how long to wait before giving up, in units of {@code unit}
192       * @param unit a {@code TimeUnit} determining how to interpret the timeout parameter
193       * @return the number of elements transferred
194       * @throws InterruptedException if interrupted while waiting
195       */
196      public static <E> int drain(BlockingQueue<E> q, Collection<? super E> buffer, int numElements,
197          long timeout, TimeUnit unit) throws InterruptedException {
198        Preconditions.checkNotNull(buffer);
199        /*
200         * This code performs one System.nanoTime() more than necessary, and in return, the time to
201         * execute Queue#drainTo is not added *on top* of waiting for the timeout (which could make
202         * the timeout arbitrarily inaccurate, given a queue that is slow to drain).
203         */
204        long deadline = System.nanoTime() + unit.toNanos(timeout);
205        int added = 0;
206        while (added < numElements) {
207          // we could rely solely on #poll, but #drainTo might be more efficient when there are multiple
208          // elements already available (e.g. LinkedBlockingQueue#drainTo locks only once)
209          added += q.drainTo(buffer, numElements - added);
210          if (added < numElements) { // not enough elements immediately available; will have to poll
211            E e = q.poll(deadline - System.nanoTime(), TimeUnit.NANOSECONDS);
212            if (e == null) {
213              break; // we already waited enough, and there are no more elements in sight
214            }
215            buffer.add(e);
216            added++;
217          }
218        }
219        return added;
220      }
221      
222      /**
223       * Drains the queue as {@linkplain #drain(BlockingQueue, Collection, int, long, TimeUnit)}, 
224       * but with a different behavior in case it is interrupted while waiting. In that case, the 
225       * operation will continue as usual, and in the end the thread's interruption status will be set 
226       * (no {@code InterruptedException} is thrown). 
227       * 
228       * @param q the blocking queue to be drained
229       * @param buffer where to add the transferred elements
230       * @param numElements the number of elements to be waited for
231       * @param timeout how long to wait before giving up, in units of {@code unit}
232       * @param unit a {@code TimeUnit} determining how to interpret the timeout parameter
233       * @return the number of elements transferred
234       */
235      public static <E> int drainUninterruptibly(BlockingQueue<E> q, Collection<? super E> buffer, 
236          int numElements, long timeout, TimeUnit unit) {
237        Preconditions.checkNotNull(buffer);
238        long deadline = System.nanoTime() + unit.toNanos(timeout);
239        int added = 0;
240        boolean interrupted = false;
241        try {
242          while (added < numElements) {
243            // we could rely solely on #poll, but #drainTo might be more efficient when there are 
244            // multiple elements already available (e.g. LinkedBlockingQueue#drainTo locks only once)
245            added += q.drainTo(buffer, numElements - added);
246            if (added < numElements) { // not enough elements immediately available; will have to poll
247              E e; // written exactly once, by a successful (uninterrupted) invocation of #poll
248              while (true) {
249                try {
250                  e = q.poll(deadline - System.nanoTime(), TimeUnit.NANOSECONDS);
251                  break;
252                } catch (InterruptedException ex) {
253                  interrupted = true; // note interruption and retry
254                }
255              }
256              if (e == null) {
257                break; // we already waited enough, and there are no more elements in sight
258              }
259              buffer.add(e);
260              added++;
261            }
262          }
263        } finally {
264          if (interrupted) {
265            Thread.currentThread().interrupt();
266          }
267        }
268        return added;
269      }
270    }