aboutsummaryrefslogtreecommitdiffstats
path: root/kotlinx-coroutines-core/native/src/internal/CopyOnWriteList.kt
diff options
context:
space:
mode:
Diffstat (limited to 'kotlinx-coroutines-core/native/src/internal/CopyOnWriteList.kt')
-rw-r--r--kotlinx-coroutines-core/native/src/internal/CopyOnWriteList.kt104
1 files changed, 104 insertions, 0 deletions
diff --git a/kotlinx-coroutines-core/native/src/internal/CopyOnWriteList.kt b/kotlinx-coroutines-core/native/src/internal/CopyOnWriteList.kt
new file mode 100644
index 00000000..c81f6530
--- /dev/null
+++ b/kotlinx-coroutines-core/native/src/internal/CopyOnWriteList.kt
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+package kotlinx.coroutines.internal
+
+@Suppress("UNCHECKED_CAST")
+internal class CopyOnWriteList<E>(private var array: Array<Any?> = arrayOfNulls(4)) : AbstractMutableList<E>() {
+
+ private var _size = 0
+ override val size: Int get() = _size
+
+ override fun add(element: E): Boolean {
+ val newSize = if (_size == array.size) array.size * 2 else array.size
+ val update = array.copyOf(newSize)
+ update[_size++] = element
+ array = update
+ return true
+ }
+
+ override fun add(index: Int, element: E) {
+ rangeCheck(index)
+ val update = arrayOfNulls<Any?>(if (array.size == _size) array.size * 2 else array.size)
+ array.copyInto(
+ destination = update,
+ endIndex = index
+ )
+ update[index] = element
+ array.copyInto(
+ destination = update,
+ destinationOffset = index + 1,
+ startIndex = index,
+ endIndex = _size + 1
+ )
+ ++_size
+ array = update
+ }
+
+ override fun remove(element: E): Boolean {
+ val index = array.indexOf(element as Any)
+ if (index == -1) {
+ return false
+ }
+
+ removeAt(index)
+ return true
+ }
+
+ override fun removeAt(index: Int): E {
+ rangeCheck(index)
+ modCount++
+ val n = array.size
+ val element = array[index]
+ val update = arrayOfNulls<Any>(n)
+ array.copyInto(
+ destination = update,
+ endIndex = index
+ )
+ array.copyInto(
+ destination = update,
+ destinationOffset = index,
+ startIndex = index + 1,
+ endIndex = n
+ )
+ array = update
+ --_size
+ return element as E
+ }
+
+ override fun iterator(): MutableIterator<E> = IteratorImpl(array as Array<E>, size)
+
+ override fun listIterator(): MutableListIterator<E> = throw UnsupportedOperationException("Operation is not supported")
+
+ override fun listIterator(index: Int): MutableListIterator<E> = throw UnsupportedOperationException("Operation is not supported")
+
+ override fun isEmpty(): Boolean = size == 0
+
+ override fun set(index: Int, element: E): E = throw UnsupportedOperationException("Operation is not supported")
+
+ override fun get(index: Int): E = array[rangeCheck(index)]!! as E
+
+ private class IteratorImpl<E>(private var array: Array<E>, private val size: Int) : MutableIterator<E> {
+
+ private var current = 0
+
+ override fun hasNext(): Boolean = current != size
+
+ override fun next(): E {
+ if (!hasNext()) {
+ throw NoSuchElementException()
+ }
+
+ return array[current++]!!
+ }
+
+ override fun remove() = throw UnsupportedOperationException("Operation is not supported")
+ }
+
+ private fun rangeCheck(index: Int) = index.apply {
+ if (index < 0 || index >= _size) {
+ throw IndexOutOfBoundsException("index: $index, size: $size")
+ }
+ }
+}