• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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