From ee9b6cd87f1775b02e06248cdca1a0f41b274ea0 Mon Sep 17 00:00:00 2001
From: tursom <tursom@foxmail.com>
Date: Tue, 18 Feb 2020 13:55:24 +0800
Subject: [PATCH] add concurrent list

---
 src/main/kotlin/cn/tursom/core/Tools.kt       |   2 +-
 .../core/datastruct/AbstractMutableList.kt    | 131 +++++++++++++
 .../cn/tursom/core/datastruct/SubList.kt      |  20 ++
 .../concurrent/BlockingArrayList.kt           |   3 +
 .../concurrent/BlockingLinkedList.kt          |   5 +
 .../datastruct/concurrent/BlockingList.kt     |  33 ++++
 .../concurrent/ConcurrentLinkedList.kt        | 174 ++++++++++++++++++
 7 files changed, 367 insertions(+), 1 deletion(-)
 create mode 100644 src/main/kotlin/cn/tursom/core/datastruct/AbstractMutableList.kt
 create mode 100644 src/main/kotlin/cn/tursom/core/datastruct/SubList.kt
 create mode 100644 src/main/kotlin/cn/tursom/core/datastruct/concurrent/BlockingArrayList.kt
 create mode 100644 src/main/kotlin/cn/tursom/core/datastruct/concurrent/BlockingLinkedList.kt
 create mode 100644 src/main/kotlin/cn/tursom/core/datastruct/concurrent/BlockingList.kt
 create mode 100644 src/main/kotlin/cn/tursom/core/datastruct/concurrent/ConcurrentLinkedList.kt

diff --git a/src/main/kotlin/cn/tursom/core/Tools.kt b/src/main/kotlin/cn/tursom/core/Tools.kt
index bfae1e3..98d752e 100644
--- a/src/main/kotlin/cn/tursom/core/Tools.kt
+++ b/src/main/kotlin/cn/tursom/core/Tools.kt
@@ -250,7 +250,7 @@ fun <T> T.println(): T {
 }
 
 @Suppress("UNCHECKED_CAST")
-fun <T> Any.cast(): T = this as T
+fun <T> Any?.cast(): T = this as T
 
 inline fun loop(`continue`: () -> Boolean = { true }, action: () -> Unit) {
   while (`continue`()) action()
diff --git a/src/main/kotlin/cn/tursom/core/datastruct/AbstractMutableList.kt b/src/main/kotlin/cn/tursom/core/datastruct/AbstractMutableList.kt
new file mode 100644
index 0000000..620c04c
--- /dev/null
+++ b/src/main/kotlin/cn/tursom/core/datastruct/AbstractMutableList.kt
@@ -0,0 +1,131 @@
+package cn.tursom.core.datastruct
+
+interface AbstractMutableList<T> : MutableList<T> {
+  override fun contains(element: T): Boolean {
+    forEach {
+      if (it == element) return true
+    }
+    return false
+  }
+
+  override fun subList(fromIndex: Int, toIndex: Int): MutableList<T> {
+    return SubList(this, fromIndex, toIndex)
+  }
+
+  override fun clear() {
+    repeat(size) {
+      removeAt(size - 1)
+    }
+  }
+
+  override fun containsAll(elements: Collection<T>): Boolean {
+    elements.forEach {
+      if (contains(it).not()) {
+        return false
+      }
+    }
+    return true
+  }
+
+  override fun indexOf(element: T): Int {
+    forEachIndexed { i, t ->
+      if (element == t) return i
+    }
+    return -1
+  }
+
+  override fun isEmpty(): Boolean = size == 0
+
+  override fun lastIndexOf(element: T): Int {
+    var last = -1
+    forEachIndexed { index, t ->
+      if (t == element) last = index
+    }
+    return last
+  }
+
+  override fun addAll(index: Int, elements: Collection<T>): Boolean {
+    elements.forEachIndexed { i, t ->
+      add(index + i, t)
+    }
+    return true
+  }
+
+  override fun addAll(elements: Collection<T>): Boolean {
+    elements.forEach {
+      add(it)
+    }
+    return true
+  }
+
+  override fun retainAll(elements: Collection<T>): Boolean {
+    val iterator = iterator()
+    var changed = false
+    while (iterator.hasNext()) {
+      val value = iterator.next()
+      if (elements.contains(value).not()) {
+        iterator.remove()
+        changed = true
+      }
+    }
+    return changed
+  }
+
+  override fun listIterator(): MutableListIterator<T> = listIterator(0)
+
+  override fun remove(element: T): Boolean {
+    val index = indexOf(element)
+    return if (index < 0) {
+      false
+    } else {
+      removeAt(index)
+      true
+    }
+  }
+
+  override fun removeAll(elements: Collection<T>): Boolean {
+    var changed = false
+    elements.forEach {
+      if (remove(it)) {
+        changed = true
+      }
+    }
+    return changed
+  }
+
+  override fun iterator(): MutableIterator<T> = listIterator()
+
+  override fun listIterator(index: Int): MutableListIterator<T> = AbstractListIterator(this, index)
+
+  class AbstractListIterator<T>(val list: MutableList<T>, var index: Int = 0) : MutableListIterator<T> {
+    init {
+      index--
+    }
+
+    override fun hasPrevious(): Boolean = index > 0
+
+    override fun previousIndex(): Int = index - 1
+    override fun previous(): T {
+      return list[--index]
+    }
+
+    override fun add(element: T) {
+      list.add(index, element)
+    }
+
+    override fun hasNext(): Boolean = index < list.size
+    override fun nextIndex(): Int = index + 1
+    override fun next(): T {
+      return list[++index]
+    }
+
+    override fun remove() {
+      list.removeAt(index)
+    }
+
+    override fun set(element: T) {
+      list[index] = element
+    }
+  }
+}
+
diff --git a/src/main/kotlin/cn/tursom/core/datastruct/SubList.kt b/src/main/kotlin/cn/tursom/core/datastruct/SubList.kt
new file mode 100644
index 0000000..28e58a8
--- /dev/null
+++ b/src/main/kotlin/cn/tursom/core/datastruct/SubList.kt
@@ -0,0 +1,20 @@
+package cn.tursom.core.datastruct
+
+class SubList<T>(
+  val parent: MutableList<T>,
+  val fromIndex: Int,
+  val toIndex: Int
+) : AbstractMutableList<T> {
+  override val size: Int get() = toIndex - fromIndex
+
+  override fun add(element: T): Boolean {
+    parent.add(toIndex, element)
+    return true
+  }
+
+  override fun add(index: Int, element: T) = parent.add(fromIndex + index, element)
+  override fun removeAt(index: Int): T = parent.removeAt(fromIndex + index)
+  override fun retainAll(elements: Collection<T>): Boolean = parent.retainAll(elements)
+  override fun set(index: Int, element: T): T = parent.set(fromIndex + index, element)
+  override fun get(index: Int): T = parent[fromIndex + index]
+}
\ No newline at end of file
diff --git a/src/main/kotlin/cn/tursom/core/datastruct/concurrent/BlockingArrayList.kt b/src/main/kotlin/cn/tursom/core/datastruct/concurrent/BlockingArrayList.kt
new file mode 100644
index 0000000..87984c6
--- /dev/null
+++ b/src/main/kotlin/cn/tursom/core/datastruct/concurrent/BlockingArrayList.kt
@@ -0,0 +1,3 @@
+package cn.tursom.core.datastruct.concurrent
+
+class BlockingArrayList<T> : BlockingList<T>(ArrayList<T>())
\ No newline at end of file
diff --git a/src/main/kotlin/cn/tursom/core/datastruct/concurrent/BlockingLinkedList.kt b/src/main/kotlin/cn/tursom/core/datastruct/concurrent/BlockingLinkedList.kt
new file mode 100644
index 0000000..ec540b2
--- /dev/null
+++ b/src/main/kotlin/cn/tursom/core/datastruct/concurrent/BlockingLinkedList.kt
@@ -0,0 +1,5 @@
+package cn.tursom.core.datastruct.concurrent
+
+import java.util.*
+
+class BlockingLinkedList<T> : BlockingList<T>(LinkedList<T>())
diff --git a/src/main/kotlin/cn/tursom/core/datastruct/concurrent/BlockingList.kt b/src/main/kotlin/cn/tursom/core/datastruct/concurrent/BlockingList.kt
new file mode 100644
index 0000000..ff6e45e
--- /dev/null
+++ b/src/main/kotlin/cn/tursom/core/datastruct/concurrent/BlockingList.kt
@@ -0,0 +1,33 @@
+package cn.tursom.core.datastruct.concurrent
+
+import cn.tursom.core.datastruct.AbstractMutableList
+import java.util.*
+import java.util.concurrent.locks.ReentrantReadWriteLock
+import kotlin.concurrent.read
+import kotlin.concurrent.write
+
+open class BlockingList<T>(val list: MutableList<T> = LinkedList()) : AbstractMutableList<T> {
+  private var lock = ReentrantReadWriteLock()
+  override val size: Int get() = list.size
+
+  override fun add(element: T): Boolean = lock.write {
+    list.add(element)
+  }
+
+  override fun add(index: Int, element: T) = lock.write {
+    list.add(index, element)
+  }
+
+  override fun removeAt(index: Int): T = lock.write {
+    list.removeAt(index)
+  }
+
+  override fun set(index: Int, element: T): T = lock.write {
+    list.set(index, element)
+  }
+
+  override fun get(index: Int): T = lock.read {
+    list[index]
+  }
+}
+
diff --git a/src/main/kotlin/cn/tursom/core/datastruct/concurrent/ConcurrentLinkedList.kt b/src/main/kotlin/cn/tursom/core/datastruct/concurrent/ConcurrentLinkedList.kt
new file mode 100644
index 0000000..0efc026
--- /dev/null
+++ b/src/main/kotlin/cn/tursom/core/datastruct/concurrent/ConcurrentLinkedList.kt
@@ -0,0 +1,174 @@
+package cn.tursom.core.datastruct.concurrent
+
+import cn.tursom.core.datastruct.AbstractMutableList
+import java.util.concurrent.locks.ReentrantReadWriteLock
+import kotlin.concurrent.read
+import kotlin.concurrent.write
+
+@Suppress("MemberVisibilityCanBePrivate")
+class ConcurrentLinkedList<T> : AbstractMutableList<T> {
+  private var length = 0
+  private var lock = ReentrantReadWriteLock()
+  private var root = Node()
+
+  override val size: Int get() = length
+
+  override fun get(index: Int): T {
+    val p = prevNodeOfIndex(index).next
+    @Suppress("UNCHECKED_CAST")
+    return p.value as T
+  }
+
+  override fun add(element: T): Boolean = lock.write {
+    addBeforeNode(root.prev, element)
+    return true
+  }
+
+  override fun add(index: Int, element: T) = if (index > size) {
+    throw IndexOutOfBoundsException()
+  } else lock.write {
+    val p = prevNodeOfIndex(index)
+    addBeforeNode(p, element)
+  }
+
+  fun addAndGetIndex(element: T): Int = lock.write {
+    addBeforeNode(root.prev, element)
+    return size - 1
+  }
+
+  fun addAndGetIterator(element: T): MutableListIterator<T> = lock.write {
+    addBeforeNode(root.prev, element)
+    return Iterator(size - 1, root.prev)
+  }
+
+  override fun clear() = lock.write {
+    length = 0
+    root.next = root
+    root.prev = root
+  }
+
+  override fun removeAt(index: Int): T = if (index > size) {
+    throw IndexOutOfBoundsException()
+  } else lock.write {
+    val p = prevNodeOfIndex(index)
+    val removed = p.next
+    p.next = p.next.next
+    p.next.prev = p
+    @Suppress("UNCHECKED_CAST")
+    removed.value as T
+  }
+
+  override fun set(index: Int, element: T): T = if (index < 0 || index > size) {
+    throw IndexOutOfBoundsException()
+  } else lock.read {
+    val p = prevNodeOfIndex(index).next
+    val oldValue = p.value
+    p.value = element
+    @Suppress("UNCHECKED_CAST")
+    oldValue as T
+  }
+
+  override fun listIterator(index: Int): MutableListIterator<T> = Iterator(index)
+
+  override fun toString(): String {
+    return if (length == 0) {
+      "[]"
+    } else {
+      val sb = StringBuilder("[")
+      var node = root.next
+      while (node != root) {
+        sb.append("${node.value}, ")
+        node = node.next
+      }
+      repeat(2) {
+        sb.deleteCharAt(sb.length - 1)
+      }
+      sb.append(']')
+      sb.toString()
+    }
+  }
+
+  private fun addBeforeNode(p: Node, value: T) = lock.write {
+    length++
+    val new = Node(value, p.next.prev, p.next)
+    new.next.prev = new
+    new.prev.next = new
+  }
+
+  private fun prevNodeOfIndex(index: Int): Node = if (index < 0) {
+    root
+  } else lock.read {
+    var p = root
+    if (index <= length / 2) {
+      // 从前向后遍历
+      repeat(index) {
+        p = p.next
+      }
+    } else {
+      // 从后向前遍历
+      repeat(length - index + 1) {
+        p = p.prev
+      }
+    }
+    return p
+  }
+
+  private inner class Node {
+    var value: T?
+    var prev: Node
+    var next: Node
+
+    constructor(value: T? = null, prev: Node, next: Node) {
+      this.value = value
+      this.next = next
+      this.prev = prev
+    }
+
+    constructor(value: T? = null) {
+      this.value = value
+      this.next = this
+      this.prev = this
+    }
+  }
+
+  private inner class Iterator(
+    var index: Int,
+    var p: Node = prevNodeOfIndex(index - 1)
+  ) : MutableListIterator<T> {
+
+    override fun hasPrevious(): Boolean = p.prev != root
+
+    override fun previousIndex(): Int = index - 1
+    override fun previous(): T {
+      p = p.prev
+      index--
+      return get()
+    }
+
+    override fun add(element: T) {
+      addBeforeNode(p, element)
+    }
+
+    override fun nextIndex(): Int = index + 1
+    override fun hasNext(): Boolean = p.next != root
+    override fun next(): T {
+      p = p.next
+      index++
+      return get()
+    }
+
+    override fun remove() = lock.write {
+      p.next.prev = p.prev
+      p.prev.next = p.next
+    }
+
+    override fun set(element: T) {
+      p.value = element
+    }
+
+    fun get(): T {
+      @Suppress("UNCHECKED_CAST")
+      return p.value as T
+    }
+  }
+}
\ No newline at end of file