[K/N] Catch concurrent modifications of ArrayList
As a part of efforts to stabilize Native stdlib.
This commit is contained in:
committed by
Space Team
parent
c53b49d7fa
commit
9d8d9d000f
@@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user