blob: 2896c2eac55b686ed9f8d8c15aeb0573b8997a89 [file] [log] [blame]
/*
* Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/
package kotlinx.coroutines.internal
import kotlinx.atomicfu.*
@Suppress("UNCHECKED_CAST")
internal class CopyOnWriteList<E> : AbstractMutableList<E>() {
private val _array = atomic(arrayOfNulls<Any?>(0))
private var array: Array<Any?>
get() = _array.value
set(value) { _array.value = value }
override val size: Int
get() = array.size
override fun add(element: E): Boolean {
val n = size
val update = array.copyOf(n + 1)
update[n] = element
array = update
return true
}
override fun add(index: Int, element: E) {
rangeCheck(index)
val n = size
val update = arrayOfNulls<Any?>(n + 1)
array.copyInto(destination = update, endIndex = index)
update[index] = element
array.copyInto(destination = update, destinationOffset = index + 1, startIndex = index, endIndex = n + 1)
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)
val n = size
val element = array[index]
val update = arrayOfNulls<Any>(n - 1)
array.copyInto(destination = update, endIndex = index)
array.copyInto(destination = update, destinationOffset = index, startIndex = index + 1, endIndex = n)
array = update
return element as E
}
override fun iterator(): MutableIterator<E> = IteratorImpl(array as Array<E>)
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 val array: Array<E>) : MutableIterator<E> {
private var current = 0
override fun hasNext(): Boolean = current != array.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")
}
}