Updated comments and readme. Cleaned up imports and (unnecessary) API for suspending pools. Fixed class access.

This commit is contained in:
nathan 2020-10-06 19:55:17 +02:00
parent a232cec99c
commit 694a28f2b0
8 changed files with 89 additions and 137 deletions

View File

@ -1,67 +1,42 @@
ObjectPool
==========
###### [![Dorkbox](https://badge.dorkbox.com/dorkbox.svg "Dorkbox")](https://git.dorkbox.com/dorkbox/ObjectPool) [![Github](https://badge.dorkbox.com/github.svg "Github")](https://github.com/dorkbox/ObjectPool) [![Gitlab](https://badge.dorkbox.com/gitlab.svg "Gitlab")](https://gitlab.com/dorkbox/ObjectPool) [![Bitbucket](https://badge.dorkbox.com/bitbucket.svg "Bitbucket")](https://bitbucket.org/dorkbox/ObjectPool)
###### [![Dorkbox](https://badge.dorkbox.com/dorkbox.svg "Dorkbox")](https://git.dorkbox.com/dorkbox/ObjectPool) [![Github](https://badge.dorkbox.com/github.svg "Github")](https://github.com/dorkbox/ObjectPool) [![Gitlab](https://badge.dorkbox.com/gitlab.svg "Gitlab")](https://gitlab.com/dorkbox/ObjectPool)
This provides an ObjectPool, for providing for a safe, and fixed sized pool of objects. This is only recommended in systems were garbage collection is to be kept to a minimum, and the created objects are large.
- This is for cross-platform use, specifically - linux 32/64, mac 32/64, and windows 32/64. Java 6+
- This is for cross-platform use, specifically - linux 32/64, mac 32/64, and windows 32/64. Java 11+
Usage:
```
ObjectPool<T> pool = ObjectPool.NonBlocking(new PoolableObject<T>() {
/**
* Called when an object is returned to the pool, useful for resetting an objects state, for example.
*/
public
void onReturn(T object) {
object.foo = 0;
object.bar = null;
}
val <T> pool = ObjectPool.nonBlocking(PoolObject<T>() {
/**
* Called when an object is returned to the pool, useful for resetting an objects state, for example.
*/
fun onReturn(`object`: Foo) {
object.foo = 0;
object.bar = null;
}
/**
* Called when an object is taken from the pool, useful for setting an objects state, for example.
*/
public
void onTake(T object) {
}
/**
* Takes an object from the pool, if there is no object available, will create a new object.
*/
fun onTake(`object`: Foo) {
}
/**
* Called when a new instance is created
*/
@Override
public
T create() {
return new Object();
}
/**
* @return a new object instance created by the pool.
*/
override fun newInstance(): Foo {
return Foo();
}
});
/**
* Takes an object from the pool. If the pool is a {@link BlockingPool}, this will wait until an item is available in
* the pool.
* <p/>
* This method catches {@link InterruptedException} and discards it silently.
*/
T take();
/**
* Takes an object from the pool. If the pool is a {@link BlockingPool}, this will wait until an item is available in the pool.
*/
T takeInterruptibly() throws InterruptedException;
/**
* Return object to the pool. If the pool is a {@link BlockingPool}, this will wake the threads that have blocked during take/takeInterruptibly()
*/
void put(T object);
/**
* @return a new object instance created by the pool.
*/
T newInstance();
val foo = pool.take()
pool.put(foo)
```
&nbsp;
@ -76,7 +51,7 @@ Maven Info
<dependency>
<groupId>com.dorkbox</groupId>
<artifactId>ObjectPool</artifactId>
<version>2.11</version>
<version>3.0</version>
</dependency>
</dependencies>
```
@ -86,15 +61,12 @@ Gradle Info
````
dependencies {
...
compile 'com.dorkbox:ObjectPool:2.11'
compile 'com.dorkbox:ObjectPool:3.0'
}
````
Or if you don't want to use Maven, you can access the files directly here:
https://repo1.maven.org/maven2/com/dorkbox/ObjectPool/
License
---------
This project is © 2014 dorkbox llc, and is distributed under the terms of the Apache v2.0 License. See file "LICENSE" for further references.
This project is © 2020 dorkbox llc, and is distributed under the terms of the Apache v2.0 License. See file "LICENSE" for further
references.

View File

@ -20,10 +20,10 @@ import dorkbox.objectPool.blocking.BlockingPool
import dorkbox.objectPool.nonBlocking.NonBlockingPool
import dorkbox.objectPool.nonBlocking.NonBlockingSoftPool
import dorkbox.objectPool.suspending.SuspendingPool
import kotlinx.coroutines.channels.Channel
import java.lang.ref.SoftReference
import java.util.*
import java.util.concurrent.BlockingQueue
import java.util.concurrent.ConcurrentLinkedQueue
/**
* @author dorkbox, llc
@ -32,49 +32,34 @@ object ObjectPool {
/**
* Gets the version number.
*/
val version: String
get() = "3.0"
const val version = "3.0"
/**
* Creates a blocking pool of a specific size, where the entire pool is initially filled, and when the pool is empty, a
* Creates a suspending pool of a specific size, where the entire pool is initially filled, and when the pool is empty, a
* [Pool.take] will wait for a corresponding [Pool.put].
*
* @param poolObject controls the lifecycle of the pooled objects.
* @param size the size of the pool to create
* @param <T> the type of object used in the pool
*
* @return a blocking pool using the default ArrayBlockingQueue implementation of a specific size
* @return a suspending pool using the kotlin Channel implementation of a specific size
*/
fun <T> suspending(poolObject: SuspendingPoolObject<T>, size: Int): dorkbox.objectPool.SuspendingPool<T> {
return suspending(poolObject, Channel(size), size)
return SuspendingPool(poolObject, size)
}
/**
* Creates a blocking pool of a specific size, where the entire pool is initially filled, and when the pool is empty, a
* Creates a high-performance blocking pool of a specific size, where the entire pool is initially filled, and when the pool is empty, a
* [Pool.take] will wait for a corresponding [Pool.put].
*
* @param poolObject controls the lifecycle of the pooled objects.
* @param size the size of the pool to create
* @param <T> the type of object used in the pool
*
* @return a blocking pool using the default ArrayBlockingQueue implementation of a specific size
*/
fun <T> suspending(poolObject: SuspendingPoolObject<T>, channel: Channel<T>, size: Int): dorkbox.objectPool.SuspendingPool<T> {
return SuspendingPool(poolObject, channel, size)
}
/**
* Creates a blocking pool of a specific size, where the entire pool is initially filled, and when the pool is empty, a
* [Pool.take] will wait for a corresponding [Pool.put].
*
* @param poolObject controls the lifecycle of the pooled objects.
* @param size the size of the pool to create
* @param <T> the type of object used in the pool
*
* @return a blocking pool using the default ArrayBlockingQueue implementation of a specific size
* @return a blocking pool using the DisruptorBlockingQueue implementation of a specific size
*/
fun <T> blocking(poolObject: PoolObject<T>, size: Int): Pool<T> {
return BlockingPool(poolObject, DisruptorBlockingQueue<T>(size), size)
return blocking(poolObject, DisruptorBlockingQueue(size), size)
}
/**
@ -85,30 +70,34 @@ object ObjectPool {
* @param queue the blocking queue implementation to use
* @param <T> the type of object used in the pool
*
* @return a blocking pool using the default ArrayBlockingQueue implementation of a specific size
* @return a blocking pool using the specified [BlockingQueue] implementation of a specific size
*/
fun <T> blocking(poolObject: PoolObject<T>, queue: BlockingQueue<T>, size: Int): Pool<T> {
return BlockingPool(poolObject, queue, size)
}
/**
* Creates a non-blocking pool which will grow as much as needed. If the pool is empty, new objects will be created. The items in the
* pool will never expire or be automatically garbage collected. (see [.NonBlockingSoftReference] for pooled objects
* that will expire/GC as needed).
* Creates a non-blocking pool which will grow as much as needed.
*
* If the pool is empty, new objects will be created. The items in the pool will never expire or be automatically garbage collected.
*
* (see [ObjectPool.nonBlockingSoftReference] for pooled objects that will expire/GC as needed).
*
* @param poolObject controls the lifecycle of the pooled objects.
* @param <T> the type of object used in the pool
*
* @return a blocking pool using the default ConcurrentLinkedQueue implementation
* @return a blocking pool using the default [ConcurrentLinkedQueue] implementation
*/
fun <T> nonBlocking(poolObject: PoolObject<T>): Pool<T> {
return NonBlockingPool(poolObject)
}
/**
* Creates a non-blocking pool which will grow as much as needed. If the pool is empty, new objects will be created. The items in the
* pool will never expire or be automatically garbage collected. (see [.NonBlockingSoftReference] for pooled objects
* that will expire/GC as needed).
* Creates a non-blocking pool which will grow as much as needed.
*
* If the pool is empty, new objects will be created. The items in the pool will never expire or be automatically garbage collected.
*
* (see [ObjectPool.nonBlockingSoftReference] for pooled objects that will expire/GC as needed).
*
* @param poolObject controls the lifecycle of the pooled objects.
* @param queue the queue implementation to use
@ -121,9 +110,12 @@ object ObjectPool {
}
/**
* Creates a non-blocking pool which will grow as much as needed. If the pool is empty, new objects will be created. The items in the
* pool will expire and be automatically Garbage Collected in response to memory demand. (See [.NonBlocking]
* for pooled objects that will never expire).
* Creates a non-blocking pool which will grow as much as needed.
*
* If the pool is empty, new objects will be created. The items in the pool will expire and be automatically Garbage Collected in
* response to memory demand.
*
* (See [ObjectPool.nonBlocking] for pooled objects that will never expire).
*
* @param poolObject controls the lifecycle of the pooled objects.
* @param <T> the type of object used in the pool
@ -135,15 +127,18 @@ object ObjectPool {
}
/**
* Creates a non-blocking pool which will grow as much as needed. If the pool is empty, new objects will be created. The items in the
* pool will expire and be automatically Garbage Collected in response to memory demand. (See [.NonBlocking]
* for pooled objects that will never expire).
* Creates a non-blocking pool which will grow as much as needed.
*
* If the pool is empty, new objects will be created. The items in the pool will expire and be automatically Garbage Collected in
* response to memory demand.
*
* (See [ObjectPool.nonBlocking] for pooled objects that will never expire).
*
* @param poolObject controls the lifecycle of the pooled objects.
* @param queue the queue implementation to use
* @param <T> the type of object used in the pool
*
* @return a blocking pool using the default ConcurrentLinkedQueue implementation
* @return a blocking pool using the specified Queue implementation
*/
fun <T> nonBlockingSoftReference(poolObject: PoolObject<T>, queue: Queue<SoftReference<T>>): Pool<T> {
return NonBlockingSoftPool(poolObject, queue)

View File

@ -29,14 +29,15 @@ interface Pool<T> {
fun take(): T
/**
* Takes an object from the pool. If the pool is a [BlockingPool], this will wait until an item is available in the pool.
* Takes an object from the pool. If the pool is a [BlockingPool], this will wait until an item is available in
* the pool, catching [InterruptedException].
*
* @throws InterruptedException
*/
fun takeInterruptibly(): T
/**
* Return object to the pool. If the pool is a [BlockingPool], this will wake the threads that have blocked during take/takeInterruptibly()
* Return object to the pool. If the pool is a [BlockingPool] or [SuspendingPool], this will wake the threads that have blocked during take/takeInterruptibly()
*/
fun put(`object`: T)

View File

@ -23,7 +23,6 @@ interface SuspendingPool<T> {
* Takes an object from the pool. If the pool is a [SuspendingPool], this will wait until an item is available in
* the pool.
*
*
* This method catches [InterruptedException] and discards it silently.
*/
suspend fun take(): T

View File

@ -25,7 +25,7 @@ import java.util.concurrent.BlockingQueue
*
* @author dorkbox, llc
*/
internal class BlockingPool<T> internal constructor(
internal class BlockingPool<T> constructor(
private val poolObject: PoolObject<T>,
private val queue: BlockingQueue<T>,
size: Int) : Pool<T> {
@ -38,8 +38,6 @@ internal class BlockingPool<T> internal constructor(
}
}
/**
* Takes an object from the pool, Blocks until an item is available in the pool.
*

View File

@ -15,15 +15,18 @@
*/
package dorkbox.objectPool.nonBlocking
import dorkbox.objectPool.ObjectPool
import dorkbox.objectPool.Pool
import dorkbox.objectPool.PoolObject
import java.util.*
import java.util.concurrent.ConcurrentLinkedQueue
/**
* A non-blocking pool which will grow as much as needed. If the pool is empty, new objects will be created. The items in the
* pool will never expire or be automatically garbage collected. (see [ObjectPool.NonBlockingSoftReference] for pooled objects
* that will expire/GC as needed).
* A non-blocking pool which will grow as much as needed. If the pool is empty, new objects will be created.
*
* The items in the pool will never expire or be automatically garbage collected.
*
* (see [ObjectPool.nonBlockingSoftReference] for pooled objects that will expire/GC as needed).
*
* @author dorkbox, llc
*/
@ -31,26 +34,15 @@ internal class NonBlockingPool<T>(
private val poolObject: PoolObject<T>,
private val queue: Queue<T> = ConcurrentLinkedQueue()) : Pool<T> {
/**
* Takes an object from the pool, Blocks until an item is available in the pool.
*
* This method catches [InterruptedException] and discards it silently.
* Takes an object from the pool, if there is no object available, will create a new object.
*/
override fun take(): T {
return try {
takeInterruptibly()
} catch (e: InterruptedException) {
val newInstance = newInstance()
poolObject.onTake(newInstance)
newInstance
}
return takeInterruptibly()
}
/**
* Takes an object from the pool, Blocks until an item is available in the pool.
*
* @throws InterruptedException
* Takes an object from the pool, if there is no object available, will create a new object.
*/
override fun takeInterruptibly(): T {
var take = queue.poll()
@ -63,7 +55,7 @@ internal class NonBlockingPool<T>(
}
/**
* Return object to the pool, waking the threads that have blocked during take()
* Return object to the pool
*/
override fun put(`object`: T) {
poolObject.onReturn(`object`)

View File

@ -15,6 +15,7 @@
*/
package dorkbox.objectPool.nonBlocking
import dorkbox.objectPool.ObjectPool
import dorkbox.objectPool.Pool
import dorkbox.objectPool.PoolObject
import java.lang.ref.SoftReference
@ -22,9 +23,11 @@ import java.util.*
import java.util.concurrent.ConcurrentLinkedQueue
/**
* A non-blocking pool which will grow as much as needed. If the pool is empty, new objects will be created. The items in the
* pool will expire and be automatically Garbage Collected in response to memory demand. (See [ObjectPool.NonBlocking]
* for pooled objects that will never expire).
* A non-blocking pool which will grow as much as needed. If the pool is empty, new objects will be created.
*
* The items in the pool will expire and be automatically Garbage Collected in response to memory demand.
*
* (See [ObjectPool.nonBlocking] for pooled objects that will never expire).
*
* @author dorkbox, llc
*/
@ -33,24 +36,14 @@ internal class NonBlockingSoftPool<T>(
private val queue: Queue<SoftReference<T>> = ConcurrentLinkedQueue()) : Pool<T> {
/**
* Takes an object from the pool, Blocks until an item is available in the pool.
*
* This method catches [InterruptedException] and discards it silently.
* Takes an object from the pool, if there is no object available, will create a new object.
*/
override fun take(): T {
return try {
takeInterruptibly()
} catch (e: InterruptedException) {
val newInstance = newInstance()
poolObject.onTake(newInstance)
newInstance
}
return takeInterruptibly()
}
/**
* Takes an object from the pool, Blocks until an item is available in the pool.
*
* @throws InterruptedException
* Takes an object from the pool, if there is no object available, will create a new object.
*/
override fun takeInterruptibly(): T {
val obj: T?

View File

@ -15,22 +15,24 @@
*/
package dorkbox.objectPool.suspending
import dorkbox.objectPool.Pool
import dorkbox.objectPool.SuspendingPool
import dorkbox.objectPool.SuspendingPoolObject
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.runBlocking
/**
* A blocking, suspending pool of a specific size, where the entire pool is initially filled, and when the pool
* is empty, a [Pool.take] will wait for a corresponding [Pool.put].
* A suspending pool of a specific size, where the entire pool is initially filled, and when the pool is empty,
* a [Pool.take] will wait for a corresponding [Pool.put].
*
* @author dorkbox, llc
*/
internal class SuspendingPool<T> internal constructor(
internal class SuspendingPool<T> constructor(
private val poolObject: SuspendingPoolObject<T>,
private val channel: Channel<T>,
size: Int) : SuspendingPool<T> {
private val channel = Channel<T>(size)
init {
runBlocking {
for (x in 0 until size) {