Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
6b6a28fd
提交
6b6a28fd
authored
10 年前
作者:
Thomas Mueller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
A concurrent queue, to replace the array list of old roots (work in progress)
上级
9b92121d
隐藏空白字符变更
内嵌
并排
正在显示
4 个修改的文件
包含
182 行增加
和
46 行删除
+182
-46
ConcurrentLinkedList.java
h2/src/main/org/h2/mvstore/ConcurrentLinkedList.java
+19
-18
ConcurrentRing.java
h2/src/main/org/h2/mvstore/ConcurrentRing.java
+99
-0
MVMap.java
h2/src/main/org/h2/mvstore/MVMap.java
+11
-11
TestConcurrentLinkedList.java
h2/src/test/org/h2/test/store/TestConcurrentLinkedList.java
+53
-17
没有找到文件。
h2/src/main/org/h2/mvstore/ConcurrentLinkedList.java
浏览文件 @
6b6a28fd
...
...
@@ -39,38 +39,39 @@ public class ConcurrentLinkedList<K> {
}
}
public
void
removeFirst
(
K
obj
)
{
public
boolean
removeFirst
(
K
obj
)
{
Entry
<
K
>
x
=
head
;
if
(
x
==
null
)
{
return
;
if
(
x
==
null
||
x
.
obj
!=
obj
)
{
return
false
;
}
if
(
x
.
obj
.
equals
(
obj
))
{
if
(
head
==
tail
)
{
tail
=
x
.
next
;
}
head
=
x
.
next
;
if
(
head
==
tail
)
{
tail
=
x
.
next
;
}
head
=
x
.
next
;
return
true
;
}
public
void
removeLast
(
K
obj
)
{
public
boolean
removeLast
(
K
obj
)
{
Entry
<
K
>
x
=
head
;
if
(
x
==
null
)
{
return
;
return
false
;
}
Entry
<
K
>
prev
=
null
;
while
(
x
.
next
!=
null
)
{
prev
=
x
;
x
=
x
.
next
;
}
if
(
x
.
obj
.
equals
(
obj
)
)
{
if
(
prev
!=
null
)
{
prev
.
next
=
null
;
}
if
(
head
==
tail
)
{
head
=
prev
;
}
tail
=
prev
;
if
(
x
.
obj
!=
obj
)
{
return
false
;
}
if
(
prev
!=
null
)
{
prev
.
next
=
null
;
}
if
(
head
==
tail
)
{
head
=
prev
;
}
tail
=
prev
;
return
true
;
}
public
Iterator
<
K
>
iterator
()
{
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/mvstore/ConcurrentRing.java
0 → 100644
浏览文件 @
6b6a28fd
/*
* Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
mvstore
;
import
java.util.Iterator
;
/**
* A ring buffer that supports concurrent access.
*
* @param <K> the key type
*/
public
class
ConcurrentRing
<
K
>
{
K
[]
buffer
;
volatile
int
readPos
;
volatile
int
writePos
;
@SuppressWarnings
(
"unchecked"
)
public
ConcurrentRing
()
{
buffer
=
(
K
[])
new
Object
[
4
];
}
public
K
peekFirst
()
{
return
buffer
[
getIndex
(
readPos
)];
}
public
K
peekLast
()
{
return
buffer
[
getIndex
(
writePos
-
1
)];
}
public
void
add
(
K
obj
)
{
buffer
[
getIndex
(
writePos
)]
=
obj
;
writePos
++;
if
(
writePos
-
readPos
>=
buffer
.
length
)
{
// double the capacity
@SuppressWarnings
(
"unchecked"
)
K
[]
b2
=
(
K
[])
new
Object
[
buffer
.
length
*
2
];
for
(
int
i
=
readPos
;
i
<
writePos
;
i
++)
{
K
x
=
buffer
[
getIndex
(
i
)];
int
i2
=
i
&
b2
.
length
-
1
;
b2
[
i2
]
=
x
;
}
buffer
=
b2
;
}
}
public
boolean
removeFirst
(
K
obj
)
{
int
p
=
readPos
;
int
idx
=
getIndex
(
p
);
if
(
buffer
[
idx
]
!=
obj
)
{
return
false
;
}
buffer
[
idx
]
=
null
;
readPos
=
p
+
1
;
return
true
;
}
public
boolean
removeLast
(
K
obj
)
{
int
p
=
writePos
;
int
idx
=
getIndex
(
p
-
1
);
if
(
buffer
[
idx
]
!=
obj
)
{
return
false
;
}
buffer
[
idx
]
=
null
;
writePos
=
p
-
1
;
return
true
;
}
int
getIndex
(
int
pos
)
{
return
pos
&
buffer
.
length
-
1
;
}
public
Iterator
<
K
>
iterator
()
{
return
new
Iterator
<
K
>()
{
int
pos
=
readPos
;
@Override
public
boolean
hasNext
()
{
return
pos
!=
writePos
;
}
@Override
public
K
next
()
{
return
buffer
[
getIndex
(
pos
++)];
}
@Override
public
void
remove
()
{
throw
DataUtils
.
newUnsupportedOperationException
(
"remove"
);
}
};
}
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/mvstore/MVMap.java
浏览文件 @
6b6a28fd
...
...
@@ -54,8 +54,8 @@ public class MVMap<K, V> extends AbstractMap<K, V>
private
final
DataType
keyType
;
private
final
DataType
valueType
;
private
Concurrent
LinkedList
<
Page
>
oldRootsList
=
new
Concurrent
LinkedList
<
Page
>();
private
Concurrent
Ring
<
Page
>
oldRoots
=
new
Concurrent
Ring
<
Page
>();
private
boolean
closed
;
private
boolean
readOnly
;
...
...
@@ -720,9 +720,9 @@ public class MVMap<K, V> extends AbstractMap<K, V>
if
(
root
!=
newRoot
)
{
removeUnusedOldVersions
();
if
(
root
.
getVersion
()
!=
newRoot
.
getVersion
())
{
Page
last
=
oldRoots
List
.
peekLast
();
Page
last
=
oldRoots
.
peekLast
();
if
(
last
==
null
||
last
.
getVersion
()
!=
root
.
getVersion
())
{
oldRoots
List
.
add
(
root
);
oldRoots
.
add
(
root
);
}
}
root
=
newRoot
;
...
...
@@ -970,12 +970,12 @@ public class MVMap<K, V> extends AbstractMap<K, V>
// the map is removed later
}
else
if
(
root
.
getVersion
()
>=
version
)
{
while
(
true
)
{
Page
last
=
oldRoots
List
.
peekLast
();
Page
last
=
oldRoots
.
peekLast
();
if
(
last
==
null
)
{
break
;
}
// slow, but rollback is not a common operation
oldRoots
List
.
removeLast
(
last
);
oldRoots
.
removeLast
(
last
);
root
=
last
;
if
(
root
.
getVersion
()
<
version
)
{
break
;
...
...
@@ -995,16 +995,16 @@ public class MVMap<K, V> extends AbstractMap<K, V>
if
(
oldest
==
-
1
)
{
return
;
}
Page
last
=
oldRoots
List
.
peekLast
();
Page
last
=
oldRoots
.
peekLast
();
// TODO why is this?
;
oldest
--;
while
(
true
)
{
Page
p
=
oldRoots
List
.
peekFirst
();
Page
p
=
oldRoots
.
peekFirst
();
if
(
p
==
null
||
p
.
getVersion
()
>=
oldest
||
p
==
last
)
{
break
;
}
oldRoots
List
.
removeFirst
(
p
);
oldRoots
.
removeFirst
(
p
);
}
}
...
...
@@ -1166,12 +1166,12 @@ public class MVMap<K, V> extends AbstractMap<K, V>
store
.
getFileStore
()
==
null
))
{
newest
=
r
;
}
else
{
Page
last
=
oldRoots
List
.
peekFirst
();
Page
last
=
oldRoots
.
peekFirst
();
if
(
last
==
null
||
version
<
last
.
getVersion
())
{
// smaller than all in-memory versions
return
store
.
openMapVersion
(
version
,
id
,
this
);
}
Iterator
<
Page
>
it
=
oldRoots
List
.
iterator
();
Iterator
<
Page
>
it
=
oldRoots
.
iterator
();
while
(
it
.
hasNext
())
{
Page
p
=
it
.
next
();
if
(
p
.
getVersion
()
>
version
)
{
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/store/TestConcurrentLinkedList.java
浏览文件 @
6b6a28fd
...
...
@@ -8,8 +8,9 @@ package org.h2.test.store;
import
java.util.Iterator
;
import
java.util.LinkedList
;
import
java.util.Random
;
import
java.util.concurrent.atomic.AtomicInteger
;
import
org.h2.mvstore.Concurrent
LinkedList
;
import
org.h2.mvstore.Concurrent
Ring
;
import
org.h2.test.TestBase
;
import
org.h2.util.Task
;
...
...
@@ -47,18 +48,26 @@ public class TestConcurrentLinkedList extends TestBase {
private
void
testPerformance
(
final
boolean
stock
)
{
System
.
out
.
print
(
stock
?
"stock "
:
"custom "
);
long
start
=
System
.
currentTimeMillis
();
final
ConcurrentLinkedList
<
Integer
>
test
=
new
ConcurrentLinkedList
<
Integer
>();
// final ConcurrentLinkedList<Integer> test = new ConcurrentLinkedList<Integer>();
final
ConcurrentRing
<
Integer
>
test
=
new
ConcurrentRing
<
Integer
>();
final
LinkedList
<
Integer
>
x
=
new
LinkedList
<
Integer
>();
final
AtomicInteger
counter
=
new
AtomicInteger
();
Task
task
=
new
Task
()
{
@Override
public
void
call
()
throws
Exception
{
while
(!
stop
)
{
if
(
stock
)
{
synchronized
(
x
)
{
x
.
peekFirst
();
Integer
y
=
x
.
peekFirst
();
if
(
y
==
null
)
{
counter
.
incrementAndGet
();
}
}
}
else
{
test
.
peekFirst
();
Integer
y
=
test
.
peekFirst
();
if
(
y
==
null
)
{
counter
.
incrementAndGet
();
}
}
}
}
...
...
@@ -66,28 +75,29 @@ public class TestConcurrentLinkedList extends TestBase {
task
.
execute
();
test
.
add
(-
1
);
x
.
add
(-
1
);
for
(
int
i
=
0
;
i
<
10
000000
;
i
++)
{
Integer
value
=
i
;
for
(
int
i
=
0
;
i
<
2
000000
;
i
++)
{
Integer
value
=
Integer
.
valueOf
(
i
&
63
)
;
if
(
stock
)
{
synchronized
(
x
)
{
Integer
f
=
x
.
peekLast
();
if
(
!
f
.
equals
(
value
)
)
{
if
(
f
!=
value
)
{
x
.
add
(
i
);
}
}
Math
.
sin
(
i
);
synchronized
(
x
)
{
if
(
x
.
peek
()
!=
x
.
peekLast
())
{
x
.
peek
();
if
(
x
.
peekFirst
()
!=
x
.
peekLast
())
{
x
.
removeFirst
();
}
}
}
else
{
Integer
f
=
test
.
peekLast
();
if
(
!
f
.
equals
(
value
)
)
{
if
(
f
!=
value
)
{
test
.
add
(
i
);
}
if
(
test
.
peekFirst
()
!=
test
.
peekLast
())
{
f
=
test
.
peekFirst
();
Math
.
sin
(
i
);
f
=
test
.
peekFirst
();
if
(
f
!=
test
.
peekLast
())
{
test
.
removeFirst
(
f
);
}
}
...
...
@@ -97,14 +107,40 @@ public class TestConcurrentLinkedList extends TestBase {
}
private
void
testConcurrent
()
{
// TODO Auto-generated method stub
// final ConcurrentLinkedList<Integer> test = new ConcurrentLinkedList<Integer>();
final
ConcurrentRing
<
Integer
>
test
=
new
ConcurrentRing
<
Integer
>();
final
AtomicInteger
counter
=
new
AtomicInteger
();
final
AtomicInteger
size
=
new
AtomicInteger
();
Task
task
=
new
Task
()
{
@Override
public
void
call
()
{
while
(!
stop
)
{
if
(
size
.
get
()
<
10
)
{
test
.
add
(
counter
.
getAndIncrement
());
size
.
getAndIncrement
();
}
}
}
};
task
.
execute
();
for
(
int
i
=
0
;
i
<
1000000
;)
{
Integer
x
=
test
.
peekFirst
();
if
(
x
==
null
)
{
continue
;
}
assertEquals
(
i
,
x
.
intValue
());
if
(
test
.
removeFirst
(
x
))
{
size
.
getAndDecrement
();
i
++;
}
}
task
.
get
();
}
private
void
testRandomized
()
{
Random
r
=
new
Random
(
0
);
for
(
int
i
=
0
;
i
<
100
;
i
++)
{
Concurrent
LinkedList
<
Integer
>
test
=
new
ConcurrentLinkedList
<
Integer
>();
Concurrent
Ring
<
Integer
>
test
=
new
ConcurrentRing
<
Integer
>();
LinkedList
<
Integer
>
x
=
new
LinkedList
<
Integer
>();
StringBuilder
buff
=
new
StringBuilder
();
for
(
int
j
=
0
;
j
<
10000
;
j
++)
{
...
...
@@ -120,7 +156,7 @@ public class TestConcurrentLinkedList extends TestBase {
}
case
1
:
{
Integer
value
=
x
.
peek
();
if
(
value
!=
null
&&
r
.
nextBoolean
(
))
{
if
(
value
!=
null
&&
(
x
.
size
()
>
5
||
r
.
nextBoolean
()
))
{
buff
.
append
(
"removeFirst\n"
);
x
.
removeFirst
();
test
.
removeFirst
(
value
);
...
...
@@ -132,7 +168,7 @@ public class TestConcurrentLinkedList extends TestBase {
}
case
2
:
{
Integer
value
=
x
.
peekLast
();
if
(
value
!=
null
&&
r
.
nextBoolean
(
))
{
if
(
value
!=
null
&&
(
x
.
size
()
>
5
||
r
.
nextBoolean
()
))
{
buff
.
append
(
"removeLast\n"
);
x
.
removeLast
();
test
.
removeLast
(
value
);
...
...
This diff is collapsed.
Click to expand it.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论