1 /* 2 * Copyright 2025 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.tracing.driver 18 19 /** 20 * An Object pool that keeps track of scrap objects in a fixed size [ArrayDeque]. 21 * 22 * @param size represents the size of the Object pool. 23 * @param factory is a function that can be used to create the instances of the Object for the pool. 24 * @param T represents an object that be re-used. 25 */ 26 internal class Pool<T>( 27 private val size: Int, 28 private val isDebug: Boolean, 29 private val factory: (owner: Pool<T>) -> T 30 ) { 31 private var counter: AtomicLong? = null 32 33 init { 34 if (isDebug) { 35 counter = AtomicLong(0L) 36 } 37 } 38 39 // This class is intentionally lock free. 40 // This is because, the only place where we recycle objects in the pool is in the TraceSink 41 // and that effectively behaves as-if it were single threaded. 42 private val scrapPool: ArrayDeque<T> = ArrayDeque(size) 43 44 init { 45 // Eagerly create the objects for the pool <lambda>null46 repeat(size) { scrapPool.addLast(factory(this)) } 47 } 48 49 /** Obtain an instance of the object from the pool. */ obtainnull50 internal fun obtain(): T { 51 if (isDebug) { 52 counter?.incrementAndGet() 53 } 54 return scrapPool.removeFirstOrNull() ?: factory(this) 55 } 56 releasenull57 internal fun release(element: T) { 58 if (isDebug) { 59 counter?.decrement() 60 } 61 if (scrapPool.size < size) { 62 scrapPool.addFirst(element) 63 } 64 } 65 countnull66 internal fun count(): Long { 67 return counter?.get() ?: 0L 68 } 69 } 70