/// <summary> /// Returns/adds an object to the pool so it can be reused. /// </summary> /// <param name="value"></param> /// <remarks> /// <para>Items will be returned to the pool if it is not full, otherwise no action is taken and no error is reported.</para> /// <para>If the policy for the pool specifies <see cref="PooledItemInitialization.AsyncReturn"/> the item will be queued for re-intialisation on a background thread before being returned to the pool, control will return to the caller once the item has been queued even if it has not yet been fully re-initialised and returned to the pool.</para> /// <para>If the item is NOT returned to the pool, and {T} implements <see cref="System.IDisposable"/>, the instance will be disposed before the method returns.</para> /// <para>Calling this method on a disposed pool will dispose the returned item if it supports <see cref="IDisposable"/>, but takes no other action and throws no error.</para> /// <para>This method is 'thread safe', though it is possible for multiple threads returning items at the same time to add items beyond the maximum pool size. This should be rare and have few ill effects. Over time the pool will likely return to it's normal size.</para> /// </remarks> /// <exception cref="ArgumentNullException">Thrown if the <paramref name="value"/> is null.</exception> /// <exception cref="InvalidOperationException">Thrown if the <see cref="PoolPolicy{T}.ErrorOnIncorrectUsage"/> is true and the same instance already exists in the pool.</exception> public override void Add(T value) { if (value == null) { throw new ArgumentNullException(nameof(value)); } if (IsDisposed) { SafeDispose(value); return; } if (ShouldReturnToPool(value)) { if (PoolPolicy.InitializationPolicy == PooledItemInitialization.AsyncReturn) { SafeAddToReinitialiseQueue(value); } else { if (PoolPolicy.InitializationPolicy == PooledItemInitialization.Return && PoolPolicy.ReinitializeObject != null) { PoolPolicy.ReinitializeObject(value); } _Pool.Add(value); Interlocked.Increment(ref _PoolInstancesCount); } } else { SafeDispose(value); } }
/// <summary> /// Gets an item from the pool. /// </summary> /// <remarks> /// <para>If the pool is empty when the request is made, a new item is instantiated and returned. Otherwise an instance from the pool will be used.</para> /// </remarks> /// <returns>Returns an instance of {T} from the pool, or a new instance if the pool is empty.</returns> /// <exception cref="ObjectDisposedException">Thrown if the pool has been disposed.</exception> public override T Take() { CheckDisposed(); T retVal = null; if (_PoolItemIndex >= 0) { retVal = _PoolItems[_PoolItemIndex]; _PoolItems[_PoolItemIndex] = null; _PoolItemIndex--; if (retVal != null && PoolPolicy.InitializationPolicy == PooledItemInitialization.Take && PoolPolicy.ReinitializeObject != null) { PoolPolicy.ReinitializeObject(retVal); } } if (retVal == null) { retVal = PoolPolicy.Factory(this); } return(retVal); }
private void ReinitialiseAndReturnToPoolOrDispose(T value) { if (ShouldReturnToPool(value)) { PoolPolicy.ReinitializeObject(value); _Pool.Add(value); Interlocked.Increment(ref _PoolInstancesCount); } else { SafeDispose(value); } }
private bool ReinitialiseObject(T item) { try { PoolPolicy.ReinitializeObject(item); return(true); } catch (Exception ex) { OnReinitialiseError(new ReinitialiseErrorEventArgs <T>(ex, item)); SafeDispose(item); } return(false); }
private void BackgroundReinitialise() { T item = default(T); while (!_ItemsToInitialise.IsCompleted) { try { item = _ItemsToInitialise.Take(); } catch (InvalidOperationException) { if (_ItemsToInitialise.IsCompleted) { return; } } if (item != null) { if (IsDisposed) { SafeDispose(item); } else { if (PoolPolicy.ReinitializeObject != null) { PoolPolicy.ReinitializeObject(item); } if (ShouldReturnToPool(item)) { _Pool.Add(item); Interlocked.Increment(ref _PoolInstancesCount); } } } } }
/// <summary> /// Returns/adds an object to the pool so it can be reused. /// </summary> /// <param name="value"></param> /// <remarks> /// <para>Items will be returned to the pool if it is not full, otherwise no action is taken and no error is reported.</para> /// <para>If the item is NOT returned to the pool, and {T} implements <see cref="System.IDisposable"/>, the instance will be disposed before the method returns.</para> /// <para>Calling this method on a disposed pool will dispose the returned item if it supports <see cref="IDisposable"/>, but takes no other action and throws no error.</para> /// </remarks> /// <exception cref="ArgumentNullException">Thrown if the <paramref name="value"/> is null.</exception> /// <exception cref="InvalidOperationException">Thrown if the <see cref="PoolPolicy{T}.ErrorOnIncorrectUsage"/> is true and the same instance already exists in the pool.</exception> public override void Add(T value) { if (value == null) { throw new ArgumentNullException(nameof(value)); } if (!IsDisposed && ShouldReturnToPool(value)) { if (PoolPolicy.InitializationPolicy == PooledItemInitialization.Return && PoolPolicy.ReinitializeObject != null) { PoolPolicy.ReinitializeObject(value); } AddCore(value); } else { SafeDispose(value); } }
/// <summary> /// Gets an item from the pool. /// </summary> /// <remarks> /// <para>If the pool is empty when the request is made, a new item is instantiated and returned. Otherwise an instance from the pool will be used.</para> /// <para>This method is thread safe.</para> /// </remarks> /// <returns>Returns an instance of {T} from the pool, or a new instance if the pool is empty.</returns> /// <exception cref="ObjectDisposedException">Thrown if the pool has been disposed.</exception> public override T Take() { CheckDisposed(); T retVal; if (_Pool.TryTake(out retVal)) { Interlocked.Decrement(ref _PoolInstancesCount); if (PoolPolicy.InitializationPolicy == PooledItemInitialization.Take && PoolPolicy.ReinitializeObject != null) { PoolPolicy.ReinitializeObject(retVal); } } else { retVal = PoolPolicy.Factory(this); } return(retVal); }