1 /* 2 * Copyright 2021 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 androidx.compose.ui.platform 18 19 import androidx.compose.runtime.collection.mutableVectorOf 20 import java.lang.ref.Reference 21 import java.lang.ref.ReferenceQueue 22 import java.lang.ref.WeakReference 23 24 /** 25 * A simple collection that keeps values as [WeakReference]s. Elements are added with [push] and 26 * removed with [pop]. 27 */ 28 internal class WeakCache<T> { 29 private val values = mutableVectorOf<Reference<T>>() 30 private val referenceQueue = ReferenceQueue<T>() 31 32 /** 33 * Add [element] to the collection as a [WeakReference]. It will be removed when garbage 34 * collected or from [pop]. 35 */ pushnull36 fun push(element: T) { 37 clearWeakReferences() 38 values += WeakReference(element, referenceQueue) 39 } 40 41 /** 42 * Remove an element from the collection and return it. If no element is available, `null` is 43 * returned. 44 */ popnull45 fun pop(): T? { 46 clearWeakReferences() 47 48 while (values.isNotEmpty()) { 49 val item = values.removeAt(values.lastIndex).get() 50 if (item != null) { 51 return item 52 } 53 } 54 return null 55 } 56 57 /** 58 * The number of elements currently in the collection. This may change between calls if the 59 * references have been garbage collected. 60 */ 61 val size: Int 62 get() { 63 clearWeakReferences() 64 return values.size 65 } 66 clearWeakReferencesnull67 private fun clearWeakReferences() { 68 do { 69 val item: Reference<out T>? = referenceQueue.poll() 70 if (item != null) { 71 @Suppress("UNCHECKED_CAST") values.remove(item as Reference<T>) 72 } 73 } while (item != null) 74 } 75 } 76