mirror of
https://github.com/scm-manager/scm-manager.git
synced 2026-04-01 18:00:12 +02:00
added IterableQueue implementation
This commit is contained in:
204
scm-core/src/main/java/sonia/scm/collect/IterableQueue.java
Normal file
204
scm-core/src/main/java/sonia/scm/collect/IterableQueue.java
Normal file
@@ -0,0 +1,204 @@
|
||||
/**
|
||||
* Copyright (c) 2010, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
package sonia.scm.collect;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import com.google.common.collect.Iterators;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A iterable queue. The queue can have multiple consumer {@link Iterator},
|
||||
* which can iterate over all items of the queue until the end of the queue is
|
||||
* reached. The end of the queue if reached, if a producer call the method
|
||||
* {@link #endReached()} and the iterator has consumed all items of the backend
|
||||
* list.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*
|
||||
* @since 1.29
|
||||
* @param <T> type of the queued items
|
||||
*/
|
||||
public final class IterableQueue<T> implements Iterable<T>
|
||||
{
|
||||
|
||||
/**
|
||||
* the logger for IterableQueue
|
||||
*/
|
||||
private static final Logger logger =
|
||||
LoggerFactory.getLogger(IterableQueue.class);
|
||||
|
||||
//~--- constructors ---------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructs a new {@link IterableQueue} with the default implementation
|
||||
* of the backing list.
|
||||
*
|
||||
*/
|
||||
public IterableQueue()
|
||||
{
|
||||
list = Lists.newArrayList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@link IterableQueue} with the given backing list.
|
||||
*
|
||||
*
|
||||
* @param list backend list for the queue
|
||||
*/
|
||||
public IterableQueue(List<T> list)
|
||||
{
|
||||
this.list = list;
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Mark that the end of the queue is reached and notify all consuming
|
||||
* iterators.
|
||||
*
|
||||
* @throws IllegalStateException if the end of the queue if already reached
|
||||
*/
|
||||
public synchronized void endReached()
|
||||
{
|
||||
if (endReached)
|
||||
{
|
||||
throw new IllegalStateException(
|
||||
"the end of the queue is already reached");
|
||||
}
|
||||
endReached = true;
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new consuming iterator for the queue. The methods
|
||||
* {@link Iterator#hasNext()} and {@link Iterator#next()} of the
|
||||
* {@link Iterator} will block until the next item is pushed to the queue, if
|
||||
* the queue is empty and the end is not reached. The
|
||||
* {@link Iterator#remove()} method of the {@link Iterator} is not implemented
|
||||
* and will throw a {@link UnsupportedOperationException}.
|
||||
*
|
||||
*
|
||||
* @return new consuming iterator
|
||||
*/
|
||||
@Override
|
||||
public Iterator<T> iterator()
|
||||
{
|
||||
Iterator<T> iterator;
|
||||
|
||||
if (endReached)
|
||||
{
|
||||
logger.trace("create list iterator");
|
||||
iterator = Iterators.unmodifiableIterator(list.iterator());
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.trace("create queue iterator");
|
||||
iterator = new QueueIterator<T>(this);
|
||||
}
|
||||
|
||||
return iterator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Push a new item to the queue and notify all consuming iterators.
|
||||
*
|
||||
* @throws IllegalStateException if the end of the queue is already reached
|
||||
* @param item item to push to the queue
|
||||
*/
|
||||
public synchronized void push(T item)
|
||||
{
|
||||
if (endReached)
|
||||
{
|
||||
throw new IllegalStateException(
|
||||
"the end of the queue is already reached");
|
||||
}
|
||||
|
||||
list.add(item);
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current size of the queue.
|
||||
*
|
||||
*
|
||||
* @return current size
|
||||
*/
|
||||
int size()
|
||||
{
|
||||
return list.size();
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns the item at the specified index in this queue.
|
||||
*
|
||||
*
|
||||
* @param index index of the item in the queue
|
||||
*
|
||||
* @return item at the current index
|
||||
*/
|
||||
T get(int index)
|
||||
{
|
||||
return list.get(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the end of the queue is reached.
|
||||
*
|
||||
*
|
||||
* @return true if the end is reached
|
||||
*/
|
||||
boolean isEndReached()
|
||||
{
|
||||
return endReached;
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** marker for the end of the queue */
|
||||
private boolean endReached = false;
|
||||
|
||||
/** backend list of the queue */
|
||||
private List<T> list;
|
||||
}
|
||||
133
scm-core/src/main/java/sonia/scm/collect/QueueIterator.java
Normal file
133
scm-core/src/main/java/sonia/scm/collect/QueueIterator.java
Normal file
@@ -0,0 +1,133 @@
|
||||
/**
|
||||
* Copyright (c) 2010, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
package sonia.scm.collect;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import com.google.common.collect.UnmodifiableIterator;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Iterator for the {@link IterableQueue}. The {@link QueueIterator} should
|
||||
* only be created from the {@link IterableQueue} by calling the
|
||||
* {@link IterableQueue#iterator()}.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*
|
||||
* @since 1.29
|
||||
* @param <T> type of the queued items
|
||||
*/
|
||||
public final class QueueIterator<T> extends UnmodifiableIterator<T>
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructs a new {@link QueueIterator} for the given {@link IterableQueue}.
|
||||
*
|
||||
*
|
||||
* @param queue backend queue
|
||||
*/
|
||||
QueueIterator(IterableQueue<T> queue)
|
||||
{
|
||||
this.queue = queue;
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns the next item in the queue. This method will block until the next
|
||||
* item is pushed to the queue, if the queue is empty and the end is not
|
||||
* reached.
|
||||
*
|
||||
* @throws NoSuchElementException if the iteration has no more elements
|
||||
*
|
||||
* @return the next item in the queue
|
||||
*/
|
||||
@Override
|
||||
public T next()
|
||||
{
|
||||
if ( ! hasNext() ){
|
||||
throw new NoSuchElementException("no more items in the queue");
|
||||
}
|
||||
return queue.get(index++);
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns {@code true} {@code true} if the queue has more items.
|
||||
* This method will block until the next item is pushed to the queue, if the
|
||||
* queue is empty and the end is not
|
||||
* reached.
|
||||
*
|
||||
*
|
||||
* @return {@code true} {@code true} if the queue has more items
|
||||
*/
|
||||
@Override
|
||||
public boolean hasNext()
|
||||
{
|
||||
boolean result = false;
|
||||
|
||||
if (index < queue.size())
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
else if (!queue.isEndReached())
|
||||
{
|
||||
synchronized (queue)
|
||||
{
|
||||
try
|
||||
{
|
||||
queue.wait(TimeUnit.SECONDS.toMillis(10));
|
||||
result = index < queue.size();
|
||||
}
|
||||
catch (InterruptedException ex)
|
||||
{
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** queue for the iterator */
|
||||
private final IterableQueue<T> queue;
|
||||
|
||||
/** current index */
|
||||
private int index = 0;
|
||||
}
|
||||
34
scm-core/src/main/java/sonia/scm/collect/package-info.java
Normal file
34
scm-core/src/main/java/sonia/scm/collect/package-info.java
Normal file
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Copyright (c) 2010, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/** Collection classes for SCM-Manager */
|
||||
package sonia.scm.collect;
|
||||
Reference in New Issue
Block a user