diff options
Diffstat (limited to 'kotlinx-coroutines-core/native/src/internal/CopyOnWriteList.kt')
-rw-r--r-- | kotlinx-coroutines-core/native/src/internal/CopyOnWriteList.kt | 104 |
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") + } + } +} |