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