Remove unused class IterableQueue

Co-authored-by: René Pfeuffer<rene.pfeuffer@cloudogu.com>
This commit is contained in:
Rene Pfeuffer
2024-12-19 09:14:37 +01:00
parent 26c03444be
commit 45801c9813
5 changed files with 2 additions and 510 deletions

View File

@@ -0,0 +1,2 @@
- type: removed
description: Unused class `IterableQueue`

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}