From a129601d6d8fd3b5720c63daaaae108c437f77fe Mon Sep 17 00:00:00 2001
From: Christian Wulf <chw@informatik.uni-kiel.de>
Date: Thu, 12 Jun 2014 12:43:11 +0100
Subject: [PATCH] added ReservableArrayList

---
 .../ThroughputTimestampAnalysis.java          |  11 +-
 .../framework/concurrent/StageWorkList.java   |   2 +
 .../framework/concurrent/WorkerThread.java    |   6 +-
 .../java/teetime/framework/core/Context.java  |  35 ++--
 .../java/teetime/framework/core/IPipe.java    |   2 +-
 .../framework/core/IReservablePipe.java       |  10 +
 .../framework/core/ReservableContext.java     |   5 +
 .../scheduling/NextStageScheduler.java        |  12 +-
 .../framework/sequential/QueuePipe.java       |  25 ++-
 .../sequential/ReservableQueuePipe.java       |  50 +++++
 .../CircularWorkStealingDeque.java            |  28 +--
 .../java/teetime/util/list/ListContainer.java |   8 +
 .../teetime/util/list/ListContainerPool.java  |  37 ++++
 .../java/teetime/util/list/ObjectPool.java    |   9 +
 .../util/list/ObjectPooledLinkedList.java     |  50 +++++
 .../util/list/ReservableArrayList.java        | 176 ++++++++++++++++++
 .../util/list/ReservableArrayListTest.java    |  35 ++++
 17 files changed, 452 insertions(+), 49 deletions(-)
 create mode 100644 src/main/java/teetime/framework/core/IReservablePipe.java
 create mode 100644 src/main/java/teetime/framework/core/ReservableContext.java
 create mode 100644 src/main/java/teetime/framework/sequential/ReservableQueuePipe.java
 create mode 100644 src/main/java/teetime/util/list/ListContainer.java
 create mode 100644 src/main/java/teetime/util/list/ListContainerPool.java
 create mode 100644 src/main/java/teetime/util/list/ObjectPool.java
 create mode 100644 src/main/java/teetime/util/list/ObjectPooledLinkedList.java
 create mode 100644 src/main/java/teetime/util/list/ReservableArrayList.java
 create mode 100644 src/test/java/teetime/util/list/ReservableArrayListTest.java

diff --git a/src/main/java/teetime/examples/throughput/ThroughputTimestampAnalysis.java b/src/main/java/teetime/examples/throughput/ThroughputTimestampAnalysis.java
index e0838d6d..54c150d7 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 6ea46cbc..92f1c268 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 a0f7eaf9..3b419628 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 f39f5dd8..86c23b8d 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 84a1a653..a4f95347 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 00000000..27c22ebd
--- /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 00000000..26eda806
--- /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 ef7fa67f..0455e76a 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 8543ea17..17605b60 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 00000000..8165cd35
--- /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 62cca855..0aa4453c 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 00000000..f5ed946a
--- /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 00000000..2860f112
--- /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 00000000..acf01119
--- /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 00000000..567d66f9
--- /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 00000000..5c014ea9
--- /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 00000000..0c33dedf
--- /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());
+	}
+}
-- 
GitLab