|
// *************************************************************************** |
|
// This is free and unencumbered software released into the public domain. |
|
// |
|
// Anyone is free to copy, modify, publish, use, compile, sell, or |
|
// distribute this software, either in source code form or as a compiled |
|
// binary, for any purpose, commercial or non-commercial, and by any |
|
// means. |
|
// |
|
// In jurisdictions that recognize copyright laws, the author or authors |
|
// of this software dedicate any and all copyright interest in the |
|
// software to the public domain. We make this dedication for the benefit |
|
// of the public at large and to the detriment of our heirs and |
|
// successors. We intend this dedication to be an overt act of |
|
// relinquishment in perpetuity of all present and future rights to this |
|
// software under copyright law. |
|
// |
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
|
// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR |
|
// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
|
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
|
// OTHER DEALINGS IN THE SOFTWARE. |
|
// |
|
// For more information, please refer to <http://unlicense.org> |
|
// *************************************************************************** |
|
|
|
using System; |
|
using System.Collections.Concurrent; |
|
using JetBrains.Annotations; |
|
|
|
namespace Utilities.Pooling |
|
{ |
|
[PublicAPI] |
|
public class PoolEventArgs<T> : EventArgs |
|
{ |
|
public T Object { get; set; } |
|
|
|
public PoolEventArgs(T createdObject) |
|
{ |
|
Object = createdObject; |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// This class is a lock-free pool implementation. |
|
/// </summary> |
|
/// <typeparam name="T"></typeparam> |
|
[PublicAPI] |
|
public class LockFreePool<T> where T : class, LockFreePoolItem |
|
{ |
|
public long CreationCount { get; set; } |
|
public event EventHandler<PoolEventArgs<T>> Created; |
|
public event EventHandler<PoolEventArgs<T>> Reused; |
|
public event EventHandler<PoolEventArgs<T>> Returned; |
|
|
|
private readonly ConcurrentQueue<T> pool = new ConcurrentQueue<T>(); |
|
private readonly object[] constructorParameters; |
|
|
|
public LockFreePool() |
|
{ |
|
constructorParameters = new object[] {}; |
|
} |
|
|
|
/// <summary> |
|
/// Initializes a new instance of the <see cref="LockFreePool{T}" /> class. |
|
/// </summary> |
|
/// <param name="constructorParameters">The constructor parameters of the to-be-constructed pool-items.</param> |
|
public LockFreePool(object[] constructorParameters) |
|
{ |
|
this.constructorParameters = constructorParameters; |
|
} |
|
|
|
/// <summary> |
|
/// Gets the next item from the pool or constructs one if the pool is empty. |
|
/// </summary> |
|
/// <returns>An Item.</returns> |
|
public T Get() |
|
{ |
|
T result; |
|
if (!pool.TryDequeue(out result)) |
|
{ |
|
// The queue was empty. Construct new T. |
|
result = (T) Activator.CreateInstance(typeof(T), constructorParameters); |
|
Created?.Invoke(this, new PoolEventArgs<T>(result)); |
|
CreationCount++; |
|
} |
|
else |
|
{ |
|
Reused?.Invoke(this, new PoolEventArgs<T>(result)); |
|
} |
|
return result; |
|
} |
|
|
|
/// <summary> |
|
/// Return an item back to the pool. |
|
/// </summary> |
|
/// <param name="item">The item to return</param> |
|
/// <returns>This instance in order to support a fluent interface.</returns> |
|
public LockFreePool<T> Return(T item) |
|
{ |
|
item.Reset(); |
|
pool.Enqueue(item); |
|
Returned?.Invoke(this, new PoolEventArgs<T>(item)); |
|
return this; |
|
} |
|
|
|
/// <summary> |
|
/// Gets the number of currently enqueued items. |
|
/// </summary> |
|
/// <returns>A number.</returns> |
|
public int Count() |
|
{ |
|
return pool.Count; |
|
} |
|
|
|
/// <summary> |
|
/// Clears this instance. |
|
/// </summary> |
|
/// <returns>This instance in order to support a fluent interface.</returns> |
|
public LockFreePool<T> Clear() |
|
{ |
|
pool.Clear(); |
|
return this; |
|
} |
|
} |
|
} |