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 }