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