diff --git a/src/main/java/teetime/examples/throughput/ThroughputTimestampAnalysis.java b/src/main/java/teetime/examples/throughput/ThroughputTimestampAnalysis.java index e0838d6dffb40e064322a4a92bced627e27fc6f3..54c150d7f587cb4bb4d6a594f57119debe54314f 100644 --- a/src/main/java/teetime/examples/throughput/ThroughputTimestampAnalysis.java +++ b/src/main/java/teetime/examples/throughput/ThroughputTimestampAnalysis.java @@ -30,6 +30,7 @@ import teetime.framework.core.IStage; import teetime.framework.core.Pipeline; import teetime.framework.sequential.MethodCallPipe; import teetime.framework.sequential.QueuePipe; +import teetime.framework.sequential.ReservableQueuePipe; import teetime.stage.CollectorSink; import teetime.stage.NoopFilter; import teetime.stage.StartTimestampFilter; @@ -96,13 +97,13 @@ public class ThroughputTimestampAnalysis extends Analysis { if (this.shouldUseQueue) { // connect stages by pipes - QueuePipe.connect(objectProducer.outputPort, startTimestampFilter.inputPort); - QueuePipe.connect(startTimestampFilter.outputPort, noopFilters[0].inputPort); + ReservableQueuePipe.connect(objectProducer.outputPort, startTimestampFilter.inputPort); + ReservableQueuePipe.connect(startTimestampFilter.outputPort, noopFilters[0].inputPort); for (int i = 1; i < noopFilters.length; i++) { - QueuePipe.connect(noopFilters[i - 1].outputPort, noopFilters[i].inputPort); + ReservableQueuePipe.connect(noopFilters[i - 1].outputPort, noopFilters[i].inputPort); } - QueuePipe.connect(noopFilters[noopFilters.length - 1].outputPort, stopTimestampFilter.inputPort); - QueuePipe.connect(stopTimestampFilter.outputPort, collectorSink.objectInputPort); + ReservableQueuePipe.connect(noopFilters[noopFilters.length - 1].outputPort, stopTimestampFilter.inputPort); + ReservableQueuePipe.connect(stopTimestampFilter.outputPort, collectorSink.objectInputPort); } else { startTimestampFilter.setSchedulable(false); for (NoopFilter<TimestampObject> noopFilter : noopFilters) { diff --git a/src/main/java/teetime/framework/concurrent/StageWorkList.java b/src/main/java/teetime/framework/concurrent/StageWorkList.java index 6ea46cbceb0d22edcc377508b6638bd914ca89f9..92f1c268a1f3fb9aec28e367cd6d02b373fbf84b 100644 --- a/src/main/java/teetime/framework/concurrent/StageWorkList.java +++ b/src/main/java/teetime/framework/concurrent/StageWorkList.java @@ -7,6 +7,7 @@ import java.util.List; import teetime.framework.core.IOutputPort; import teetime.framework.core.IStage; +@Deprecated public class StageWorkList implements IStageWorkList { // private static final Log LOG = LogFactory.getLog(StageWorkList.class); @@ -67,6 +68,7 @@ public class StageWorkList implements IStageWorkList { return this.workList.toString(); } + @Override public void pushAll(final IOutputPort<?, ?>[] outputPorts) { final Collection<IStage> filteredCollection = new ArrayList<IStage>(outputPorts.length); for (final IOutputPort<?, ?> outputPort : outputPorts) { diff --git a/src/main/java/teetime/framework/concurrent/WorkerThread.java b/src/main/java/teetime/framework/concurrent/WorkerThread.java index a0f7eaf9eaa3bd2ba422e1448cb2efde0a950d8c..3b419628eebb43e57274931dcfa25c82a03d3058 100644 --- a/src/main/java/teetime/framework/concurrent/WorkerThread.java +++ b/src/main/java/teetime/framework/concurrent/WorkerThread.java @@ -39,7 +39,7 @@ import teetime.util.StopWatch; */ public class WorkerThread extends Thread { - private static final int NUM_ITERATIONS_TO_MEASURE = 10000; + private static final int NUM_ITERATIONS_TO_MEASURE = 100000; private final IPipeline pipeline; private IStageScheduler stageScheduler; @@ -225,11 +225,11 @@ public class WorkerThread extends Thread { this.pipeline.fireStartNotification(); } - private void startStageExecution(final IStage stage) { + private final void startStageExecution(final IStage stage) { // System.out.println("Executing stage: " + stage); } - private void finishStageExecution(final IStage stage, final boolean executedSuccessfully) { + private final void finishStageExecution(final IStage stage, final boolean executedSuccessfully) { if (!executedSuccessfully) { // statistics this.executedUnsuccessfullyCount++; } diff --git a/src/main/java/teetime/framework/core/Context.java b/src/main/java/teetime/framework/core/Context.java index f39f5dd89e6de0f45501c603e79f105f1fe4dad9..86c23b8d791d131acb154bf581a38f5b092ef7bb 100644 --- a/src/main/java/teetime/framework/core/Context.java +++ b/src/main/java/teetime/framework/core/Context.java @@ -5,14 +5,14 @@ import java.util.List; /** * @author Christian Wulf - * + * * @since 1.10 */ public class Context<S extends IStage> { /** * @author Christian Wulf - * + * * @since 1.10 */ private static class InputPortContainer { @@ -61,7 +61,7 @@ public class Context<S extends IStage> { } /** - * + * * @param inputPort * @return * @since 1.10 @@ -76,7 +76,7 @@ public class Context<S extends IStage> { } /** - * + * * @param inputPort * @return * @since 1.10 @@ -90,19 +90,19 @@ public class Context<S extends IStage> { return token; } - private <T> void logTransaction(final IInputPort<S, T> inputPort, final T token) { - final InputPortContainer inputPortContainer = this.inputPortContainers[inputPort.getIndex()]; + private final <T> void logTransaction(final IInputPort<S, T> inputPort, final T token) { + // final InputPortContainer inputPortContainer = this.inputPortContainers[inputPort.getIndex()]; // final List<Object> tokenList = this.pipesTakenFrom.get(inputPort); - inputPortContainer.takenElements.add(token); + // inputPortContainer.takenElements.add(token); - this.numTakenElements++; + // this.numTakenElements++; } /** - * + * * @param inputPort * @return - * + * * @since 1.10 */ public <T> T read(final IInputPort<S, T> inputPort) { @@ -113,7 +113,9 @@ public class Context<S extends IStage> { void clear() { // for (final List<Object> takenElements : this.pipesTakenFrom.values()) { for (final InputPortContainer inputPortContainer : this.inputPortContainers) { - inputPortContainer.takenElements.clear(); + // inputPortContainer.takenElements.clear(); + IReservablePipe<Object> reservablePipe = (IReservablePipe<Object>) inputPortContainer.pipe; + reservablePipe.commit(); } } @@ -124,10 +126,13 @@ public class Context<S extends IStage> { for (final InputPortContainer inputPortContainer : this.inputPortContainers) { - for (int k = inputPortContainer.takenElements.size() - 1; k >= 0; k--) { - final Object element = inputPortContainer.takenElements.get(k); - inputPortContainer.pipe.put(element); - } + // for (int k = inputPortContainer.takenElements.size() - 1; k >= 0; k--) { + // final Object element = inputPortContainer.takenElements.get(k); + // inputPortContainer.pipe.put(element); + // } + + IReservablePipe<Object> reservablePipe = (IReservablePipe<Object>) inputPortContainer.pipe; + reservablePipe.rollback(); this.numTakenElements -= inputPortContainer.takenElements.size(); } diff --git a/src/main/java/teetime/framework/core/IPipe.java b/src/main/java/teetime/framework/core/IPipe.java index 84a1a6535045d7a0e1af4447e55c403913d6960e..a4f9534732f3c5822872be422df61474369b958a 100644 --- a/src/main/java/teetime/framework/core/IPipe.java +++ b/src/main/java/teetime/framework/core/IPipe.java @@ -35,7 +35,7 @@ public interface IPipe<T> { /** * @since 1.10 */ - void put(T object); + void put(T element); /** * @since 1.10 diff --git a/src/main/java/teetime/framework/core/IReservablePipe.java b/src/main/java/teetime/framework/core/IReservablePipe.java new file mode 100644 index 0000000000000000000000000000000000000000..27c22ebdbba3a967c2af854d8a8cb11aa30b2777 --- /dev/null +++ b/src/main/java/teetime/framework/core/IReservablePipe.java @@ -0,0 +1,10 @@ +package teetime.framework.core; + +public interface IReservablePipe<T> extends IPipe<T> { + + // void reserve(T element); + + void commit(); + + void rollback(); +} diff --git a/src/main/java/teetime/framework/core/ReservableContext.java b/src/main/java/teetime/framework/core/ReservableContext.java new file mode 100644 index 0000000000000000000000000000000000000000..26eda806de48c9cef856a5a9bfe1500915ecce16 --- /dev/null +++ b/src/main/java/teetime/framework/core/ReservableContext.java @@ -0,0 +1,5 @@ +package teetime.framework.core; + +public class ReservableContext { + +} diff --git a/src/main/java/teetime/framework/scheduling/NextStageScheduler.java b/src/main/java/teetime/framework/scheduling/NextStageScheduler.java index ef7fa67f1dc4ece57f103e1941da644d52eccdf5..0455e76a053daa0883902d7c93e0a855a45be0d0 100644 --- a/src/main/java/teetime/framework/scheduling/NextStageScheduler.java +++ b/src/main/java/teetime/framework/scheduling/NextStageScheduler.java @@ -28,7 +28,7 @@ import teetime.framework.core.IStage; /** * @author Christian Wulf - * + * * @since 1.10 */ public final class NextStageScheduler implements IStageScheduler { @@ -50,17 +50,17 @@ public final class NextStageScheduler implements IStageScheduler { } @Override - public IStage get() { + public final IStage get() { return this.workList.read(); } @Override - public boolean isAnyStageActive() { + public final boolean isAnyStageActive() { return !this.workList.isEmpty(); } @Override - public void disable(final IStage stage) { + public final void disable(final IStage stage) { this.stageStateManager.disable(stage); if (this.highestPrioritizedEnabledStages.contains(stage)) { @@ -72,12 +72,12 @@ public final class NextStageScheduler implements IStageScheduler { } } -// System.out.println("highestPrioritizedEnabledStages: "+this.highestPrioritizedEnabledStages); + // System.out.println("highestPrioritizedEnabledStages: "+this.highestPrioritizedEnabledStages); stage.fireSignalClosingToAllOutputPorts(); } @Override - public void determineNextStage(final IStage stage, final boolean executedSuccessfully) { + public final void determineNextStage(final IStage stage, final boolean executedSuccessfully) { // final Collection<? extends IStage> outputStages = stage.getContext().getOutputStages(); final IOutputPort<?, ?>[] outputPorts = stage.getContext().getOutputPorts(); if (outputPorts.length > 0) { diff --git a/src/main/java/teetime/framework/sequential/QueuePipe.java b/src/main/java/teetime/framework/sequential/QueuePipe.java index 8543ea1743c690d2c89b6f77f649b0ce9fa03d71..17605b600e3199113787d00cf2c5f6ab57f9b6cb 100644 --- a/src/main/java/teetime/framework/sequential/QueuePipe.java +++ b/src/main/java/teetime/framework/sequential/QueuePipe.java @@ -15,9 +15,8 @@ ***************************************************************************/ package teetime.framework.sequential; -import java.util.LinkedList; +import java.util.ArrayList; import java.util.List; -import java.util.Queue; import teetime.framework.core.AbstractPipe; import teetime.framework.core.IInputPort; @@ -33,7 +32,11 @@ import teetime.util.concurrent.workstealing.CircularWorkStealingDeque; */ public class QueuePipe<T> extends AbstractPipe<T> { - private final Queue<T> queue = new LinkedList<T>(); + private final List<T> queue = new ArrayList<T>(10); + + // private final List<T> queue = new ReservableArrayList<T>(10); + + // private final ObjectPooledLinkedList<T> queue = new ObjectPooledLinkedList<T>(); static public <S0 extends ISource, S1 extends ISink<S1>, T> void connect(final IOutputPort<S0, ? extends T> sourcePort, final IInputPort<S1, T> targetPort) { final QueuePipe<T> pipe = new QueuePipe<T>(); @@ -44,17 +47,23 @@ public class QueuePipe<T> extends AbstractPipe<T> { @Override public void putInternal(final T element) { this.queue.add(element); + // this.queue.push(element); } + @Override public void putMultiple(final List<T> elements) { this.queue.addAll(elements); + throw new IllegalStateException(); } @Override public T tryTakeInternal() { - return this.queue.poll(); + // return this.queue.poll(); + return this.queue.remove(this.queue.size() - 1); + // return this.queue.pop(); } + @Override public T take() { final T element = this.tryTake(); if (element == null) { @@ -63,16 +72,22 @@ public class QueuePipe<T> extends AbstractPipe<T> { return element; } + @Override public T read() { - return this.queue.peek(); + // return this.queue.peek(); + return this.queue.get(this.queue.size() - 1); + // return this.queue.read(); } + @Override public List<?> tryTakeMultiple(final int numElementsToTake) { throw new IllegalStateException("Taking more than one element is not possible. You tried to take " + numElementsToTake + " items."); } + @Override public boolean isEmpty() { return this.queue.isEmpty(); + // return this.queue.size() == 0; } } diff --git a/src/main/java/teetime/framework/sequential/ReservableQueuePipe.java b/src/main/java/teetime/framework/sequential/ReservableQueuePipe.java new file mode 100644 index 0000000000000000000000000000000000000000..8165cd350e100d4644a17217ef4d6487c7ce5f48 --- /dev/null +++ b/src/main/java/teetime/framework/sequential/ReservableQueuePipe.java @@ -0,0 +1,50 @@ +package teetime.framework.sequential; + +import teetime.framework.core.IInputPort; +import teetime.framework.core.IOutputPort; +import teetime.framework.core.IReservablePipe; +import teetime.framework.core.ISink; +import teetime.framework.core.ISource; +import teetime.util.list.ReservableArrayList; + +public class ReservableQueuePipe<T> extends QueuePipe<T> implements IReservablePipe<T> { + + private final ReservableArrayList<T> reservableQueue = new ReservableArrayList<T>(10); + + static public <S0 extends ISource, S1 extends ISink<S1>, T> void connect(final IOutputPort<S0, ? extends T> sourcePort, final IInputPort<S1, T> targetPort) { + final QueuePipe<T> pipe = new ReservableQueuePipe<T>(); + pipe.setSourcePort(sourcePort); + pipe.setTargetPort(targetPort); + } + + @Override + public void commit() { + this.reservableQueue.commit(); + } + + @Override + public void rollback() { + this.reservableQueue.rollback(); + } + + @Override + public void putInternal(final T element) { + this.reservableQueue.reservedAdd(element); + } + + @Override + public T tryTakeInternal() { + return this.reservableQueue.reservedRemoveLast(); + } + + @Override + public T read() { + return this.reservableQueue.getLast(); + } + + @Override + public boolean isEmpty() { + return this.reservableQueue.isEmpty(); + } + +} diff --git a/src/main/java/teetime/util/concurrent/workstealing/CircularWorkStealingDeque.java b/src/main/java/teetime/util/concurrent/workstealing/CircularWorkStealingDeque.java index 62cca855112a631550ef575cc6c79855e68951db..0aa4453cd2dc1be54f5bdb17839428bd372ebe6a 100644 --- a/src/main/java/teetime/util/concurrent/workstealing/CircularWorkStealingDeque.java +++ b/src/main/java/teetime/util/concurrent/workstealing/CircularWorkStealingDeque.java @@ -23,11 +23,11 @@ import teetime.util.concurrent.workstealing.exception.DequeIsEmptyException; import teetime.util.concurrent.workstealing.exception.OperationAbortedException; /** - * + * * @author Christian Wulf - * + * * @see "Dynamic Circular WorkStealing Deque" - * + * * @since 1.10 */ public class CircularWorkStealingDeque<T> { @@ -42,12 +42,12 @@ public class CircularWorkStealingDeque<T> { private final AtomicLong top = new AtomicLong(); private volatile CircularArray<T> activeArray = new CircularArray<T>(LOG_INITIAL_SIZE); - private boolean casTop(final long oldVal, final long newVal) { + private final boolean casTop(final long oldVal, final long newVal) { return this.top.compareAndSet(oldVal, newVal); } /** - * + * * @param o * a non-<code>null</code> element */ @@ -67,7 +67,7 @@ public class CircularWorkStealingDeque<T> { } /** - * + * * @param elements * a non-<code>null</code> list */ @@ -92,7 +92,7 @@ public class CircularWorkStealingDeque<T> { /** * Returns and removes the latest element from this deque. - * + * * @return * <ul> * <li><code>null</code> if the deque contains no elements, @@ -124,9 +124,9 @@ public class CircularWorkStealingDeque<T> { /** * Returns and removes the latest element from this deque. - * + * * @return <i>the latest element</i>, otherwise it throws a <code>DequeIsEmptyException</code> - * + * * @throws DequeIsEmptyException */ public T popBottomEx() { @@ -170,7 +170,7 @@ public class CircularWorkStealingDeque<T> { /** * Tries to steal (return & remove) the oldest element from this deque. - * + * * @return * <ul> * <li><code>null</code> if the deque contains no elements, @@ -203,9 +203,9 @@ public class CircularWorkStealingDeque<T> { /** * Tries to steal (return & remove) the oldest element from this deque. - * + * * @return <i>the oldest element</i>, otherwise it throws a <code>DequeIsEmptyException</code> or a <code>OperationAbortedException</code> - * + * * @throws DequeIsEmptyException * @throws OperationAbortedException */ @@ -255,7 +255,7 @@ public class CircularWorkStealingDeque<T> { /** * Returns but does not remove the latest element from this deque.<br> * <i>For debugging purposes</i> - * + * * @return <ul> * <li><code>null</code> if the deque contains no elements, * <li><i>the latest element</i> otherwise @@ -287,7 +287,7 @@ public class CircularWorkStealingDeque<T> { /** * For debugging purposes - * + * * @return the number of elements this deque contains */ public long size(final Object sourceStage) { diff --git a/src/main/java/teetime/util/list/ListContainer.java b/src/main/java/teetime/util/list/ListContainer.java new file mode 100644 index 0000000000000000000000000000000000000000..f5ed946a9631d564a7ddfb2be3ce3d72e57492ee --- /dev/null +++ b/src/main/java/teetime/util/list/ListContainer.java @@ -0,0 +1,8 @@ +package teetime.util.list; + +public class ListContainer<T> { + + public T value; + public ListContainer<T> previous; + +} diff --git a/src/main/java/teetime/util/list/ListContainerPool.java b/src/main/java/teetime/util/list/ListContainerPool.java new file mode 100644 index 0000000000000000000000000000000000000000..2860f112de02f434e9b4e8dbe5f7246c5241f9b5 --- /dev/null +++ b/src/main/java/teetime/util/list/ListContainerPool.java @@ -0,0 +1,37 @@ +package teetime.util.list; + +import java.util.ArrayList; +import java.util.List; + +public class ListContainerPool<T> implements ObjectPool<ListContainer<T>> { + + private final List<ListContainer<T>> pool = new ArrayList<ListContainer<T>>(); + + public ListContainerPool(int initialPoolSize) { + while (initialPoolSize-- > 0) { + this.pool.add(this.createNew()); + } + } + + @Override + public ListContainer<T> get() { + ListContainer<T> obj; + if (this.pool.size() > 0) { + obj = this.pool.remove(this.pool.size() - 1); + } else { + obj = this.createNew(); + this.pool.add(obj); + } + return obj; + } + + private ListContainer<T> createNew() { + return new ListContainer<T>(); + } + + @Override + public void release(final ListContainer<T> obj) { + this.pool.add(obj); + } + +} diff --git a/src/main/java/teetime/util/list/ObjectPool.java b/src/main/java/teetime/util/list/ObjectPool.java new file mode 100644 index 0000000000000000000000000000000000000000..acf0111961c207b4859bc5df2c6ac63ea61c963a --- /dev/null +++ b/src/main/java/teetime/util/list/ObjectPool.java @@ -0,0 +1,9 @@ +package teetime.util.list; + +public interface ObjectPool<T> { + + T get(); + + void release(T obj); + +} diff --git a/src/main/java/teetime/util/list/ObjectPooledLinkedList.java b/src/main/java/teetime/util/list/ObjectPooledLinkedList.java new file mode 100644 index 0000000000000000000000000000000000000000..567d66f9b1b6a1134fca0d946e2159e1c3ec4d33 --- /dev/null +++ b/src/main/java/teetime/util/list/ObjectPooledLinkedList.java @@ -0,0 +1,50 @@ +package teetime.util.list; + +public class ObjectPooledLinkedList<T> { + + private final ObjectPool<ListContainer<T>> objectPool = new ListContainerPool<T>(10); + + private static final ListContainer<?> BOTTOM = new ListContainer<Object>(); + + private ListContainer<T> top; + + private int size; + + @SuppressWarnings("unchecked") + public ObjectPooledLinkedList() { + this.top = (ListContainer<T>) BOTTOM; + } + + /** + * + * @return <code>null</code> if the list is empty. + */ + public T pop() { + if (this.top == BOTTOM) { + return null; + } + T value = this.top.value; + this.top = this.top.previous; + this.size--; + return value; + } + + public void push(final T element) { + ListContainer<T> listContainer = this.objectPool.get(); + listContainer.previous = this.top; + listContainer.value = element; + this.top = listContainer; + this.size++; + } + + public T read() { + if (this.top == BOTTOM) { + return null; + } + return this.top.value; + } + + public int size() { + return this.size; + } +} diff --git a/src/main/java/teetime/util/list/ReservableArrayList.java b/src/main/java/teetime/util/list/ReservableArrayList.java new file mode 100644 index 0000000000000000000000000000000000000000..5c014ea9b984afef95ef83b533de486416a31b10 --- /dev/null +++ b/src/main/java/teetime/util/list/ReservableArrayList.java @@ -0,0 +1,176 @@ +package teetime.util.list; + +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; + +public class ReservableArrayList<T> implements List<T> { + + private final T[] elements; + + private int lastFreeIndex, lastFreeReservedIndex; + + @SuppressWarnings("unchecked") + public ReservableArrayList(final int initialSize) { + this.elements = (T[]) new Object[initialSize]; + } + + public void reservedAdd(final T element) { + this.elements[this.lastFreeReservedIndex++] = element; + } + + public void commit() { + // TODO set elements to null + this.lastFreeIndex = this.lastFreeReservedIndex; + } + + public void rollback() { + this.lastFreeReservedIndex = this.lastFreeIndex; + } + + @Override + public int size() { + return this.lastFreeIndex; + } + + @Override + public boolean isEmpty() { + return this.size() == 0; + } + + @Override + public boolean contains(final Object o) { + // TODO Auto-generated method stub + return false; + } + + @Override + public Iterator<T> iterator() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Object[] toArray() { + return this.elements; + } + + @Override + public <T> T[] toArray(final T[] a) { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean add(final T e) { + this.elements[this.lastFreeIndex++] = e; + this.lastFreeReservedIndex = this.lastFreeIndex; + return true; + } + + @Override + public boolean remove(final Object o) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean containsAll(final Collection<?> c) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean addAll(final Collection<? extends T> c) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean addAll(final int index, final Collection<? extends T> c) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean removeAll(final Collection<?> c) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean retainAll(final Collection<?> c) { + // TODO Auto-generated method stub + return false; + } + + @Override + public void clear() { + this.lastFreeIndex = this.lastFreeReservedIndex = 0; + } + + @Override + public final T get(final int index) { + T element = this.elements[index]; + return element; + } + + @Override + public T set(final int index, final T element) { + // TODO Auto-generated method stub + return null; + } + + @Override + public void add(final int index, final T element) { + // TODO Auto-generated method stub + + } + + @Override + public T remove(final int index) { + // TODO Auto-generated method stub + return null; + } + + @Override + public int indexOf(final Object o) { + // TODO Auto-generated method stub + return 0; + } + + @Override + public int lastIndexOf(final Object o) { + // TODO Auto-generated method stub + return 0; + } + + @Override + public ListIterator<T> listIterator() { + // TODO Auto-generated method stub + return null; + } + + @Override + public ListIterator<T> listIterator(final int index) { + // TODO Auto-generated method stub + return null; + } + + @Override + public List<T> subList(final int fromIndex, final int toIndex) { + // TODO Auto-generated method stub + return null; + } + + public T getLast() { + T element = this.get(this.lastFreeIndex - 1); + return element; + } + + public T reservedRemoveLast() { + T element = this.get(this.lastFreeReservedIndex--); + return element; + } +} diff --git a/src/test/java/teetime/util/list/ReservableArrayListTest.java b/src/test/java/teetime/util/list/ReservableArrayListTest.java new file mode 100644 index 0000000000000000000000000000000000000000..0c33dedfc6b244dbf5a9b33017118182996f755e --- /dev/null +++ b/src/test/java/teetime/util/list/ReservableArrayListTest.java @@ -0,0 +1,35 @@ +package teetime.util.list; + +import org.junit.Assert; +import org.junit.Test; + +public class ReservableArrayListTest { + + @Test + public void testCommit() throws Exception { + ReservableArrayList<Object> reservableArrayList = new ReservableArrayList<Object>(10); + Object element = new Object(); + reservableArrayList.reservedAdd(element); + + Assert.assertTrue(reservableArrayList.isEmpty()); + + reservableArrayList.commit(); + + Assert.assertFalse(reservableArrayList.isEmpty()); + Assert.assertEquals(element, reservableArrayList.getLast()); + } + + @Test + public void testRollback() throws Exception { + ReservableArrayList<Object> reservableArrayList = new ReservableArrayList<Object>(10); + Object element = new Object(); + reservableArrayList.reservedAdd(element); + + Assert.assertTrue(reservableArrayList.isEmpty()); + + reservableArrayList.rollback(); + + Assert.assertTrue(reservableArrayList.isEmpty()); + // Assert.assertEquals(element, reservableArrayList.getLast()); + } +}