[K/N] Catch concurrent modifications of ArrayList

As a part of efforts to stabilize Native stdlib.
This commit is contained in:
Abduqodiri Qurbonzoda
2023-05-23 22:55:13 +03:00
committed by Space Team
parent c53b49d7fa
commit 9d8d9d000f
4 changed files with 284 additions and 12 deletions
@@ -179,6 +179,10 @@ internal class ListBuilder<E> private constructor(
// ---------------------------- private ----------------------------
private fun registerModification() {
modCount += 1
}
private fun checkIsMutable() {
if (isEffectivelyReadOnly) throw UnsupportedOperationException()
}
@@ -209,6 +213,7 @@ internal class ListBuilder<E> private constructor(
}
private fun addAtInternal(i: Int, element: E) {
registerModification()
if (backing != null) {
backing.addAtInternal(i, element)
array = backing.array
@@ -220,6 +225,7 @@ internal class ListBuilder<E> private constructor(
}
private fun addAllInternal(i: Int, elements: Collection<E>, n: Int) {
registerModification()
if (backing != null) {
backing.addAllInternal(i, elements, n)
array = backing.array
@@ -236,6 +242,7 @@ internal class ListBuilder<E> private constructor(
}
private fun removeAtInternal(i: Int): E {
registerModification()
if (backing != null) {
val old = backing.removeAtInternal(i)
length--
@@ -250,6 +257,7 @@ internal class ListBuilder<E> private constructor(
}
private fun removeRangeInternal(rangeOffset: Int, rangeLength: Int) {
if (rangeLength > 0) registerModification()
if (backing != null) {
backing.removeRangeInternal(rangeOffset, rangeLength)
} else {
@@ -261,10 +269,8 @@ internal class ListBuilder<E> private constructor(
/** Retains elements if [retain] == true and removes them it [retain] == false. */
private fun retainOrRemoveAllInternal(rangeOffset: Int, rangeLength: Int, elements: Collection<E>, retain: Boolean): Int {
if (backing != null) {
val removed = backing.retainOrRemoveAllInternal(rangeOffset, rangeLength, elements, retain)
length -= removed
return removed
val removed = if (backing != null) {
backing.retainOrRemoveAllInternal(rangeOffset, rangeLength, elements, retain)
} else {
var i = 0
var j = 0
@@ -278,20 +284,24 @@ internal class ListBuilder<E> private constructor(
val removed = rangeLength - j
array.copyInto(array, startIndex = rangeOffset + rangeLength, endIndex = length, destinationOffset = rangeOffset + j)
array.resetRange(fromIndex = length - removed, toIndex = length)
length -= removed
return removed
removed
}
if (removed > 0) registerModification()
length -= removed
return removed
}
private class Itr<E> : MutableListIterator<E> {
private val list: ListBuilder<E>
private var index: Int
private var lastIndex: Int
private var expectedModCount: Int
constructor(list: ListBuilder<E>, index: Int) {
this.list = list
this.index = index
this.lastIndex = -1
this.expectedModCount = list.modCount
}
override fun hasPrevious(): Boolean = index > 0
@@ -301,32 +311,44 @@ internal class ListBuilder<E> private constructor(
override fun nextIndex(): Int = index
override fun previous(): E {
checkForComodification()
if (index <= 0) throw NoSuchElementException()
lastIndex = --index
return list.array[list.offset + lastIndex]
}
override fun next(): E {
checkForComodification()
if (index >= list.length) throw NoSuchElementException()
lastIndex = index++
return list.array[list.offset + lastIndex]
}
override fun set(element: E) {
checkForComodification()
check(lastIndex != -1) { "Call next() or previous() before replacing element from the iterator." }
list.set(lastIndex, element)
}
override fun add(element: E) {
checkForComodification()
list.add(index++, element)
lastIndex = -1
expectedModCount = list.modCount
}
override fun remove() {
checkForComodification()
check(lastIndex != -1) { "Call next() or previous() before removing element from the iterator." }
list.removeAt(lastIndex)
index = lastIndex
lastIndex = -1
expectedModCount = list.modCount
}
private fun checkForComodification() {
if (list.modCount != expectedModCount)
throw ConcurrentModificationException()
}
}
}