1 package kotlinx.coroutines.internal 2 3 import java.util.concurrent.atomic.* 4 5 /** 6 * Atomic array with lock-free reads and synchronized modifications. It logically has an unbounded size, 7 * is implicitly filled with nulls, and is resized on updates as needed to grow. 8 */ 9 internal class ResizableAtomicArray<T>(initialLength: Int) { 10 @Volatile 11 private var array = AtomicReferenceArray<T>(initialLength) 12 13 // for debug output currentLengthnull14 public fun currentLength(): Int = array.length() 15 16 public operator fun get(index: Int): T? { 17 val array = this.array // volatile read 18 return if (index < array.length()) array[index] else null 19 } 20 21 // Must not be called concurrently, e.g. always use synchronized(this) to call this function setSynchronizednull22 fun setSynchronized(index: Int, value: T?) { 23 val curArray = this.array 24 val curLen = curArray.length() 25 if (index < curLen) { 26 curArray[index] = value 27 return 28 } 29 // It would be nice to copy array in batch instead of 1 by 1, but it seems like Java has no API for that 30 val newArray = AtomicReferenceArray<T>((index + 1).coerceAtLeast(2 * curLen)) 31 for (i in 0 until curLen) newArray[i] = curArray[i] 32 newArray[index] = value 33 array = newArray // copy done 34 } 35 } 36