1 /*
2  * Copyright (C) 2023 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.google.android.torus.utils.content
18 
19 import java.lang.ref.WeakReference
20 import java.util.concurrent.ConcurrentHashMap
21 import java.util.concurrent.ConcurrentMap
22 
23 /**
24  * Class that holds the resources to be used by the engine in concurrent instances.
25  * This class is used to re-use resources that take time and memory in the system. Adding them here
26  * they can be re-used by different instances.
27  */
28 class ResourcesManager {
29     private val resources: ConcurrentMap<String, WeakReference<Any>> = ConcurrentHashMap(0)
30 
31     /**
32      * The number of resources hold.
33      */
34     var size: Int = 0
35         get() = resources.size
36         private set
37 
38     /**
39      * Stores the given resource in the ResourceManager.
40      *
41      * @param key A string identifying the resource (it can be any).
42      * @param resource The resource that we want to use in multiple instances.
43      * @return True if the resource was added; false if the resource already existed.
44      */
addResourcenull45     fun addResource(key: String, resource: Any): Boolean {
46         if (resources.contains(key) &&
47             resources[key] != null &&
48             resources[key]!!.get() != null
49         ) {
50             return false
51         }
52 
53         resources[key] = WeakReference(resource)
54         return true
55     }
56 
57     /**
58      * Gets a resource from the ResourcesManager, using the supplied function to create the resource
59      * if it didn't already exist. The key is always mapped to a non-null resource as a
60      * post-condition of this method.
61      *
62      * @param key A string identifying the resource (it can be any).
63      * @param provider A function to create the resource if it's not already indexed.
64      * @return The (new or existing) resource associated with the key.
65      */
getOrAddResourcenull66     fun <T> getOrAddResource(key: String, provider: () -> T): T {
67         val resource: T = (resources[key]?.get() as T) ?: provider()
68         resources[key] = WeakReference<Any>(resource)
69         return resource
70     }
71 
72     /**
73      * Returns the resource associated with the [key].
74      *
75      * @param key The key associated with the resource.
76      * @return The given resource; null if the resource wasn't found.
77      */
getResourcenull78     fun getResource(key: String): Any? {
79         if (!resources.contains(key)) return null
80         resources[key]?.let {
81             return it.get()
82         }
83         return null
84     }
85 
86     /**
87      * Stops the resource associated with the given [key].
88      *
89      * @param key The key associated with the resource.
90      * @return The resource reference that has been removed; null if the resource wasn't found.
91      */
removeResourcenull92     fun removeResource(key: String): WeakReference<Any>? = resources.remove(key)
93 }
94