提交 d20f5855 authored 作者: Thomas Mueller's avatar Thomas Mueller

A concurrent linked list, to replace the array list of old roots (work in progress)

上级 836d37e3
...@@ -41,24 +41,31 @@ public class ConcurrentLinkedList<K> { ...@@ -41,24 +41,31 @@ public class ConcurrentLinkedList<K> {
public void removeFirst(K obj) { public void removeFirst(K obj) {
Entry<K> x = head; Entry<K> x = head;
if (x == null || tail == x) { if (x == null) {
throw DataUtils.newUnsupportedOperationException( return;
"Must contain at least two entries");
} }
if (x.obj.equals(obj)) { if (x.obj.equals(obj)) {
if (head == tail) {
tail = x.next;
}
head = x.next; head = x.next;
} }
} }
public void removeLast(K obj) { public void removeLast(K obj) {
Entry<K> x = head; Entry<K> x = head;
Entry<K> prev = x; if (x == null) {
return;
}
Entry<K> prev = null;
while (x.next != null) { while (x.next != null) {
prev = x; prev = x;
x = x.next; x = x.next;
} }
if (x.obj.equals(obj)) { if (x.obj.equals(obj)) {
prev.next = null; if (prev != null) {
prev.next = null;
}
if (head == tail) { if (head == tail) {
head = prev; head = prev;
} }
......
...@@ -996,12 +996,8 @@ public class MVMap<K, V> extends AbstractMap<K, V> ...@@ -996,12 +996,8 @@ public class MVMap<K, V> extends AbstractMap<K, V>
return; return;
} }
Page last = oldRootsList.peekLast(); Page last = oldRootsList.peekLast();
if (oldRootsList.peekFirst() == last) {
// do nothing if there is no or only one entry
return;
}
;
// TODO why is this? // TODO why is this?
;
oldest--; oldest--;
while (true) { while (true) {
Page p = oldRootsList.peekFirst(); Page p = oldRootsList.peekFirst();
......
...@@ -13,6 +13,9 @@ import org.h2.mvstore.ConcurrentLinkedList; ...@@ -13,6 +13,9 @@ import org.h2.mvstore.ConcurrentLinkedList;
import org.h2.test.TestBase; import org.h2.test.TestBase;
import org.h2.util.Task; import org.h2.util.Task;
/**
* Test the concurrent linked list.
*/
public class TestConcurrentLinkedList extends TestBase { public class TestConcurrentLinkedList extends TestBase {
/** /**
...@@ -21,19 +24,24 @@ public class TestConcurrentLinkedList extends TestBase { ...@@ -21,19 +24,24 @@ public class TestConcurrentLinkedList extends TestBase {
* @param a ignored * @param a ignored
*/ */
public static void main(String... a) throws Exception { public static void main(String... a) throws Exception {
TestBase.createCaller().init().test(); TestConcurrentLinkedList test = (TestConcurrentLinkedList) TestBase.createCaller().init();
test.test();
test.testPerformance();
} }
@Override @Override
public void test() throws Exception { public void test() throws Exception {
testConcurrent();
testRandomized();
}
private void testPerformance() {
testPerformance(true); testPerformance(true);
testPerformance(false); testPerformance(false);
testPerformance(true); testPerformance(true);
testPerformance(false); testPerformance(false);
testPerformance(true); testPerformance(true);
testPerformance(false); testPerformance(false);
testConcurrent();
testRandomized();
} }
private void testPerformance(final boolean stock) { private void testPerformance(final boolean stock) {
...@@ -100,64 +108,49 @@ public class TestConcurrentLinkedList extends TestBase { ...@@ -100,64 +108,49 @@ public class TestConcurrentLinkedList extends TestBase {
LinkedList<Integer> x = new LinkedList<Integer>(); LinkedList<Integer> x = new LinkedList<Integer>();
StringBuilder buff = new StringBuilder(); StringBuilder buff = new StringBuilder();
for (int j = 0; j < 10000; j++) { for (int j = 0; j < 10000; j++) {
int opType = r.nextInt(10); buff.append("[" + j + "] ");
int opType = r.nextInt(3);
switch (opType) { switch (opType) {
case 0: { case 0: {
int value = r.nextInt(100); int value = r.nextInt(100);
buff.append(" add " + value); buff.append("add " + value + "\n");
test.add(value); test.add(value);
x.add(value); x.add(value);
break; break;
} }
case 1: { case 1: {
Integer value = x.peek(); Integer value = x.peek();
buff.append(" peek"); if (value != null && r.nextBoolean()) {
if (value == null) { buff.append("removeFirst\n");
assertNull(test.peekFirst()); x.removeFirst();
test.removeFirst(value);
} else { } else {
assertEquals(value.intValue(), test.peekFirst().intValue()); buff.append("removeFirst -1\n");
test.removeFirst(-1);
} }
break; break;
} }
case 2: { case 2: {
Integer value = x.peekLast(); Integer value = x.peekLast();
buff.append(" peeLast"); if (value != null && r.nextBoolean()) {
if (value == null) { buff.append("removeLast\n");
assertNull(test.peekLast()); x.removeLast();
test.removeLast(value);
} else { } else {
assertEquals(value.intValue(), test.peekLast() buff.append("removeLast -1\n");
.intValue()); test.removeLast(-1);
}
break;
}
case 3: {
if (x.size() >= 2) {
Integer value = x.peek();
if (value != null && r.nextBoolean()) {
buff.append(" removeFirst");
x.removeFirst();
test.removeFirst(value);
} else {
test.removeFirst(-1);
}
}
break;
}
case 4: {
if (x.size() >= 2) {
Integer value = x.peekLast();
if (value != null && r.nextBoolean()) {
buff.append(" removeLast");
x.removeLast();
test.removeLast(value);
} else {
test.removeLast(-1);
}
} }
break; break;
} }
} }
assertEquals(toString(x.iterator()), toString(test.iterator())); assertEquals(toString(x.iterator()), toString(test.iterator()));
if (x.isEmpty()) {
assertNull(test.peekFirst());
assertNull(test.peekLast());
} else {
assertEquals(x.peekFirst().intValue(), test.peekFirst().intValue());
assertEquals(x.peekLast().intValue(), test.peekLast().intValue());
}
} }
} }
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论