• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.systemui.kairos.internal.store
18 
19 import java.util.concurrent.atomic.AtomicReferenceArray
20 
21 /** A [Map] backed by a flat array. */
22 internal class ArrayMapK<V>(
23     val unwrapped: List<MutableMap.MutableEntry<Int, V>>,
24     val originalCapacity: Int,
25 ) : MapK<ArrayMapK.W, Int, V>, AbstractMap<Int, V>() {
26     object W
27 
28     override val entries: Set<Map.Entry<Int, V>> =
29         object : AbstractSet<Map.Entry<Int, V>>() {
30             override val size: Int
31                 get() = unwrapped.size
32 
33             override fun iterator(): Iterator<Map.Entry<Int, V>> = unwrapped.iterator()
34         }
35 }
36 
37 @Suppress("NOTHING_TO_INLINE")
asArrayHoldernull38 internal inline fun <V> MapK<ArrayMapK.W, Int, V>.asArrayHolder(): ArrayMapK<V> =
39     this as ArrayMapK<V>
40 
41 internal class MutableArrayMapK<V>
42 private constructor(private val storage: AtomicReferenceArray<MutableMap.MutableEntry<Int, V>?>) :
43     MutableMapK<ArrayMapK.W, Int, V>, AbstractMutableMap<Int, V>() {
44 
45     constructor(length: Int) : this(AtomicReferenceArray<MutableMap.MutableEntry<Int, V>?>(length))
46 
47     override fun readOnlyCopy(): ArrayMapK<V> {
48         val size1 = storage.length()
49         return ArrayMapK(
50             buildList {
51                 for (i in 0 until size1) {
52                     storage.get(i)?.let { entry -> add(StoreEntry(entry.key, entry.value)) }
53                 }
54             },
55             size1,
56         )
57     }
58 
59     override fun asReadOnly(): MapK<ArrayMapK.W, Int, V> = readOnlyCopy()
60 
61     private fun getNumEntries(): Int {
62         val capacity = storage.length()
63         var total = 0
64         for (i in 0 until capacity) {
65             storage.get(i)?.let { total++ }
66         }
67         return total
68     }
69 
70     override fun put(key: Int, value: V): V? =
71         storage.get(key)?.value.also { storage.set(key, StoreEntry(key, value)) }
72 
73     override val entries: MutableSet<MutableMap.MutableEntry<Int, V>> =
74         object : AbstractMutableSet<MutableMap.MutableEntry<Int, V>>() {
75             override val size: Int
76                 get() = getNumEntries()
77 
78             override fun add(element: MutableMap.MutableEntry<Int, V>): Boolean =
79                 (storage.get(element.key) is MutableMap.MutableEntry<*, *>).also {
80                     storage.set(element.key, element)
81                 }
82 
83             override fun iterator(): MutableIterator<MutableMap.MutableEntry<Int, V>> =
84                 object : MutableIterator<MutableMap.MutableEntry<Int, V>> {
85 
86                     var cursor = -1
87                     var nextIndex = -1
88 
89                     override fun hasNext(): Boolean {
90                         val capacity = storage.length()
91                         if (nextIndex >= capacity) return false
92                         if (nextIndex != cursor) return true
93                         while (++nextIndex < capacity) {
94                             if (storage.get(nextIndex) != null) {
95                                 return true
96                             }
97                         }
98                         return false
99                     }
100 
101                     override fun next(): MutableMap.MutableEntry<Int, V> {
102                         if (!hasNext()) throw NoSuchElementException()
103                         cursor = nextIndex
104                         return storage.get(cursor)!!
105                     }
106 
107                     override fun remove() {
108                         check(
109                             cursor >= 0 &&
110                                 cursor < storage.length() &&
111                                 storage.getAndSet(cursor, null) != null
112                         )
113                     }
114                 }
115         }
116 
117     class Factory : MutableMapK.Factory<ArrayMapK.W, Int> {
118         override fun <V> create(capacity: Int?) =
119             MutableArrayMapK<V>(checkNotNull(capacity) { "Cannot use ArrayMapK with null capacity." })
120 
121         override fun <V> create(input: MapK<ArrayMapK.W, Int, V>): MutableArrayMapK<V> {
122             val holder = input.asArrayHolder()
123             return MutableArrayMapK(
124                 AtomicReferenceArray<MutableMap.MutableEntry<Int, V>?>(holder.originalCapacity)
125                     .apply { holder.unwrapped.forEach { set(it.key, it) } }
126             )
127         }
128     }
129 }
130