mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-10-26 08:06:09 +01:00
Remove unused class IterableQueue
Co-authored-by: René Pfeuffer<rene.pfeuffer@cloudogu.com>
This commit is contained in:
2
gradle/changelog/iterable_queue.yaml
Normal file
2
gradle/changelog/iterable_queue.yaml
Normal file
@@ -0,0 +1,2 @@
|
||||
- type: removed
|
||||
description: Unused class `IterableQueue`
|
||||
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2020 - present Cloudogu GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Affero General Public License as published by the Free
|
||||
* Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
package sonia.scm.collect;
|
||||
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
/**
|
||||
* A {@link Callable} which consumes all items from a {@link QueueIterator} and
|
||||
* returns a list with all items from the queue.
|
||||
*
|
||||
*
|
||||
* @since 1.29
|
||||
*
|
||||
* @param <T> type of the queued items
|
||||
*/
|
||||
public class CallableQueueCollector<T> implements Callable<List<T>>
|
||||
{
|
||||
|
||||
private static final Logger logger =
|
||||
LoggerFactory.getLogger(CallableQueueCollector.class);
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a new {@link CallableQueueCollector} from the given
|
||||
* {@link IterableQueue}.
|
||||
*
|
||||
* @param queue queue to collect
|
||||
*/
|
||||
public CallableQueueCollector(IterableQueue<T> queue)
|
||||
{
|
||||
this.queue = queue;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a {@link List} from all items of the queue.
|
||||
*
|
||||
*
|
||||
* @return {@link List} from all items of the queue
|
||||
*/
|
||||
@Override
|
||||
public List<T> call()
|
||||
{
|
||||
logger.trace("start collecting item from queue");
|
||||
|
||||
return Lists.newArrayList(queue);
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** queue to collect items from */
|
||||
private IterableQueue<T> queue;
|
||||
}
|
||||
@@ -1,164 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2020 - present Cloudogu GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Affero General Public License as published by the Free
|
||||
* Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
package sonia.scm.collect;
|
||||
|
||||
|
||||
import com.google.common.collect.Iterators;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* An iterable queue. The queue can have multiple parallel consumer
|
||||
* {@link Iterator}s, 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. <strong>Warning: </strong> The queue iterator blocks
|
||||
* forever if the producer never call {@link #endReached()}.
|
||||
*
|
||||
*
|
||||
* @since 1.29
|
||||
* @param <T> type of the queued items
|
||||
*/
|
||||
public final class IterableQueue<T> implements Iterable<T>
|
||||
{
|
||||
private boolean endReached = false;
|
||||
|
||||
/** backend list of the queue */
|
||||
private List<T> list;
|
||||
|
||||
private static final Logger logger =
|
||||
LoggerFactory.getLogger(IterableQueue.class);
|
||||
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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<>(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.
|
||||
*/
|
||||
int size()
|
||||
{
|
||||
return list.size();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the item at the specified index in this queue.
|
||||
*/
|
||||
T get(int index)
|
||||
{
|
||||
return list.get(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the end of the queue is reached.
|
||||
*/
|
||||
boolean isEndReached()
|
||||
{
|
||||
return endReached;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,106 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2020 - present Cloudogu GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Affero General Public License as published by the Free
|
||||
* Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
package sonia.scm.collect;
|
||||
|
||||
|
||||
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()}.
|
||||
*
|
||||
*
|
||||
* @since 1.29
|
||||
* @param <T> type of the queued items
|
||||
*/
|
||||
public final class QueueIterator<T> extends UnmodifiableIterator<T>
|
||||
{
|
||||
private final IterableQueue<T> queue;
|
||||
|
||||
private int index = 0;
|
||||
|
||||
/**
|
||||
* Constructs a new {@link QueueIterator} for the given {@link IterableQueue}.
|
||||
*
|
||||
*
|
||||
* @param queue backend queue
|
||||
*/
|
||||
QueueIterator(IterableQueue<T> queue)
|
||||
{
|
||||
this.queue = queue;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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++);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns {@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.
|
||||
*/
|
||||
@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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,166 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2020 - present Cloudogu GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Affero General Public License as published by the Free
|
||||
* Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
package sonia.scm.collect;
|
||||
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
|
||||
public class IterableQueueTest
|
||||
{
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void testDuplicatedEndReached()
|
||||
{
|
||||
IterableQueue<String> queue = new IterableQueue<>();
|
||||
|
||||
queue.endReached();
|
||||
queue.endReached();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIterator()
|
||||
{
|
||||
IterableQueue<String> queue = new IterableQueue<>();
|
||||
|
||||
assertEquals(QueueIterator.class, queue.iterator().getClass());
|
||||
queue.endReached();
|
||||
assertNotEquals(QueueIterator.class, queue.iterator().getClass());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiThreaded() throws Exception
|
||||
{
|
||||
testMultiThreaded(5, 10, false, 1000);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiThreadedWithRandomSleep() throws Exception
|
||||
{
|
||||
testMultiThreaded(5, 10, true, 50);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void testPushEndReached()
|
||||
{
|
||||
IterableQueue<String> queue = new IterableQueue<>();
|
||||
|
||||
queue.push("a");
|
||||
queue.endReached();
|
||||
queue.push("b");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingleConsumer()
|
||||
{
|
||||
final IterableQueue<Integer> queue = new IterableQueue<>();
|
||||
|
||||
new Thread(new IntegerProducer(queue, false, 100)).start();
|
||||
assertResult(Lists.newArrayList(queue), 100);
|
||||
}
|
||||
|
||||
|
||||
private void assertResult(List<Integer> result, int itemCount)
|
||||
{
|
||||
assertNotNull(result);
|
||||
assertEquals(itemCount, result.size());
|
||||
|
||||
for (int c = 0; c < itemCount; c++)
|
||||
{
|
||||
assertEquals(Integer.valueOf(c), result.get(c));
|
||||
}
|
||||
}
|
||||
|
||||
private void testMultiThreaded(int threads, int consumer,
|
||||
boolean randomSleep, int itemCount)
|
||||
throws Exception
|
||||
{
|
||||
ExecutorService executor = Executors.newFixedThreadPool(threads);
|
||||
List<Future<List<Integer>>> futures = Lists.newArrayList();
|
||||
|
||||
final IterableQueue<Integer> queue = new IterableQueue<>();
|
||||
|
||||
for (int i = 0; i < consumer; i++)
|
||||
{
|
||||
Future<List<Integer>> future =
|
||||
executor.submit(new CallableQueueCollector<>(queue));
|
||||
|
||||
futures.add(future);
|
||||
}
|
||||
|
||||
new Thread(new IntegerProducer(queue, randomSleep, itemCount)).start();
|
||||
|
||||
for (Future<List<Integer>> f : futures)
|
||||
{
|
||||
assertResult(f.get(), itemCount);
|
||||
}
|
||||
}
|
||||
|
||||
private static class IntegerProducer implements Runnable
|
||||
{
|
||||
|
||||
public IntegerProducer(IterableQueue<Integer> queue, boolean randomSleep,
|
||||
int itemCount)
|
||||
{
|
||||
this.queue = queue;
|
||||
this.randomSleep = randomSleep;
|
||||
this.itemCount = itemCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
Random r = new Random();
|
||||
|
||||
for (int c = 0; c < itemCount; c++)
|
||||
{
|
||||
if (randomSleep)
|
||||
{
|
||||
try
|
||||
{
|
||||
Thread.sleep(r.nextInt(5));
|
||||
}
|
||||
catch (InterruptedException ex)
|
||||
{
|
||||
throw new RuntimeException("thread interrupted", ex);
|
||||
}
|
||||
}
|
||||
|
||||
queue.push(c);
|
||||
}
|
||||
|
||||
queue.endReached();
|
||||
}
|
||||
|
||||
IterableQueue<Integer> queue;
|
||||
|
||||
private int itemCount;
|
||||
|
||||
private boolean randomSleep;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user