Commit a1d3cf0f authored by Him188's avatar Him188

LockFreeLinkedList

parent 4b28f004
...@@ -4,17 +4,18 @@ package net.mamoe.mirai.utils ...@@ -4,17 +4,18 @@ package net.mamoe.mirai.utils
import kotlinx.coroutines.* import kotlinx.coroutines.*
import net.mamoe.mirai.test.shouldBeEqualTo import net.mamoe.mirai.test.shouldBeEqualTo
import net.mamoe.mirai.test.shouldBeFalse
import net.mamoe.mirai.test.shouldBeTrue import net.mamoe.mirai.test.shouldBeTrue
import org.junit.Test import org.junit.Test
import kotlin.system.exitProcess import kotlin.system.exitProcess
import kotlin.test.* import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertTrue
@MiraiExperimentalAPI @MiraiExperimentalAPI
internal class LockFreeLinkedListTest { internal class LockFreeLinkedListTest {
init { init {
GlobalScope.launch { GlobalScope.launch {
delay(5000) delay(30 * 1000)
exitProcess(-100) exitProcess(-100)
} }
} }
...@@ -27,26 +28,41 @@ internal class LockFreeLinkedListTest { ...@@ -27,26 +28,41 @@ internal class LockFreeLinkedListTest {
list.add(3) list.add(3)
list.add(4) list.add(4)
assertEquals(list[0], 1, "Failed on list[0]") list.size shouldBeEqualTo 4
assertEquals(list[1], 2, "Failed on list[1]")
assertEquals(list[2], 3, "Failed on list[2]")
assertEquals(list[3], 4, "Failed on list[3]")
} }
@Test @Test
fun addAndGetSingleConcurrent() { fun addAndGetConcurrent() = runBlocking {
//withContext(Dispatchers.Default){
val list = LockFreeLinkedList<Int>() val list = LockFreeLinkedList<Int>()
val add = GlobalScope.async { list.concurrentAdd(1000, 10, 1) }
val remove = GlobalScope.async { list.concurrentAdd(1000, 10, 1)
add.join() list.size shouldBeEqualTo 1000 * 10
list.concurrentDo(100, 10) { list.concurrentDo(100, 10) {
remove(1) remove(1).shouldBeTrue()
}
list.size shouldBeEqualTo 1000 * 10 - 100 * 10
//}
} }
@Test
fun addAndGetMassConcurrentAccess() = runBlocking {
val list = LockFreeLinkedList<Int>()
val addJob = async { list.concurrentAdd(5000, 10, 1) }
delay(10) // let addJob fly
if (addJob.isCompleted) {
error("Number of elements are not enough")
} }
runBlocking { list.concurrentDo(1000, 10) {
joinAll(add, remove) remove(1).shouldBeTrue()
} }
assertEquals(1000 * 10 - 100 * 10, list.size) addJob.join()
list.size shouldBeEqualTo 5000 * 10 - 1000 * 10
} }
@Test @Test
...@@ -66,37 +82,32 @@ internal class LockFreeLinkedListTest { ...@@ -66,37 +82,32 @@ internal class LockFreeLinkedListTest {
} }
@Test @Test
fun getSize() { fun addAll() {
val list = lockFreeLinkedListOf(1, 2, 3, 4, 5) val list = LockFreeLinkedList<Int>()
assertEquals(5, list.size) list.addAll(listOf(1, 2, 3, 4, 5))
list.size shouldBeEqualTo 5
val list2 = lockFreeLinkedListOf<Unit>()
assertEquals(0, list2.size)
} }
@Test @Test
fun contains() { fun clear() {
val list = lockFreeLinkedListOf<Int>() val list = LockFreeLinkedList<Int>()
assertFalse { list.contains(0) } list.addAll(listOf(1, 2, 3, 4, 5))
list.size shouldBeEqualTo 5
list.add(0) list.clear()
assertTrue { list.contains(0) } list.size shouldBeEqualTo 0
} }
@UseExperimental(ExperimentalUnsignedTypes::class)
@Test @Test
fun containsAll() { fun withInlineClassElements() {
var list = lockFreeLinkedListOf(1, 2, 3) val list = LockFreeLinkedList<UInt>()
assertTrue { list.containsAll(listOf(1, 2, 3)) } list.addAll(listOf(1u, 2u, 3u, 4u, 5u))
assertTrue { list.containsAll(listOf()) } list.size shouldBeEqualTo 5
list = lockFreeLinkedListOf(1, 2) list.toString() shouldBeEqualTo "[1, 2, 3, 4, 5]"
assertFalse { list.containsAll(listOf(1, 2, 3)) }
list = lockFreeLinkedListOf()
assertTrue { list.containsAll(listOf()) }
assertFalse { list.containsAll(listOf(1)) }
} }
/*
@Test @Test
fun indexOf() { fun indexOf() {
val list: LockFreeLinkedList<Int> = lockFreeLinkedListOf(1, 2, 3, 3) val list: LockFreeLinkedList<Int> = lockFreeLinkedListOf(1, 2, 3, 3)
...@@ -106,15 +117,6 @@ internal class LockFreeLinkedListTest { ...@@ -106,15 +117,6 @@ internal class LockFreeLinkedListTest {
assertEquals(-1, list.indexOf(4)) assertEquals(-1, list.indexOf(4))
} }
@Test
fun isEmpty() {
val list: LockFreeLinkedList<Int> = lockFreeLinkedListOf()
list.isEmpty().shouldBeTrue()
list.add(1)
list.isEmpty().shouldBeFalse()
}
@Test @Test
fun iterator() { fun iterator() {
var list: LockFreeLinkedList<Int> = lockFreeLinkedListOf(2) var list: LockFreeLinkedList<Int> = lockFreeLinkedListOf(2)
...@@ -171,68 +173,16 @@ internal class LockFreeLinkedListTest { ...@@ -171,68 +173,16 @@ internal class LockFreeLinkedListTest {
list.lastIndexOf(4) shouldBeEqualTo 4 list.lastIndexOf(4) shouldBeEqualTo 4
} }
*/
/*
companion object{
@JvmStatic
fun main(vararg args: String) {
LockFreeLinkedListTest().`lastIndexOf of many elements`()
}
}*/
@Test
fun listIterator() {
}
@Test
fun testListIterator() {
}
@Test
fun subList() {
}
@Test
fun testAdd() {
}
@Test
fun addAll() {
}
@Test
fun testAddAll() {
}
@Test
fun clear() {
}
@Test
fun removeAll() {
}
@Test
fun removeAt() {
}
@Test
fun retainAll() {
}
@Test
fun set() {
}
} }
internal fun withTimeoutBlocking(timeout: Long = 500L, block: suspend () -> Unit) = runBlocking { withTimeout(timeout) { block() } }
@MiraiExperimentalAPI @MiraiExperimentalAPI
internal suspend fun <E> LockFreeLinkedList<E>.concurrentAdd(numberOfCoroutines: Int, timesOfAdd: Int, element: E) = internal suspend inline fun <E> LockFreeLinkedList<E>.concurrentAdd(numberOfCoroutines: Int, timesOfAdd: Int, element: E) =
concurrentDo(numberOfCoroutines, timesOfAdd) { add(element) } concurrentDo(numberOfCoroutines, timesOfAdd) { add(element) }
@MiraiExperimentalAPI @MiraiExperimentalAPI
internal suspend fun <E : LockFreeLinkedList<*>> E.concurrentDo(numberOfCoroutines: Int, timesOfAdd: Int, todo: E.() -> Unit) = coroutineScope { internal suspend inline fun <E : LockFreeLinkedList<*>> E.concurrentDo(numberOfCoroutines: Int, timesOfAdd: Int, crossinline todo: E.() -> Unit) =
coroutineScope {
repeat(numberOfCoroutines) { repeat(numberOfCoroutines) {
launch { launch {
repeat(timesOfAdd) { repeat(timesOfAdd) {
...@@ -240,4 +190,4 @@ internal suspend fun <E : LockFreeLinkedList<*>> E.concurrentDo(numberOfCoroutin ...@@ -240,4 +190,4 @@ internal suspend fun <E : LockFreeLinkedList<*>> E.concurrentDo(numberOfCoroutin
} }
} }
} }
} }
\ No newline at end of file \ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment