Skip to content
This repository has been archived by the owner on May 21, 2022. It is now read-only.

Commit

Permalink
timed object pool
Browse files Browse the repository at this point in the history
  • Loading branch information
pomma89 committed Apr 7, 2017
1 parent 35b4447 commit 84dffc8
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 10 deletions.
27 changes: 23 additions & 4 deletions src/CodeProject.ObjectPool/Core/PooledObjectBuffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ public sealed class PooledObjectBuffer<T> : IEnumerable<T>
where T : PooledObject
{
#if (NET35 || NET40)
private const MethodImplOptions TryToInline = default(MethodImplOptions);
private const MethodImplOptions TryInline = default(MethodImplOptions);
#else
private const MethodImplOptions TryToInline = MethodImplOptions.AggressiveInlining;
private const MethodImplOptions TryInline = MethodImplOptions.AggressiveInlining;
#endif

/// <summary>
Expand Down Expand Up @@ -106,7 +106,7 @@ public IEnumerator<T> GetEnumerator()
/// </summary>
/// <param name="pooledObject">Output pooled object.</param>
/// <returns>True if <paramref name="pooledObject"/> has a value, false otherwise.</returns>
[MethodImpl(TryToInline)]
[MethodImpl(TryInline)]
public bool TryDequeue(out T pooledObject)
{
for (var i = 0; i < _pooledObjects.Length; i++)
Expand All @@ -127,7 +127,7 @@ public bool TryDequeue(out T pooledObject)
/// </summary>
/// <param name="pooledObject">Input pooled object.</param>
/// <returns>True if there was enough space to enqueue given object, false otherwise.</returns>
[MethodImpl(TryToInline)]
[MethodImpl(TryInline)]
public bool TryEnqueue(T pooledObject)
{
for (var i = 0; i < _pooledObjects.Length; i++)
Expand Down Expand Up @@ -186,5 +186,24 @@ public IList<T> Resize(int newCapacity)
Array.Resize(ref _pooledObjects, newCapacity);
return exceedingItems;
}

/// <summary>
/// Tries to remove given object from the buffer.
/// </summary>
/// <param name="pooledObject">Pooled object to be removed.</param>
/// <returns>True if <paramref name="pooledObject"/> has been removed, false otherwise.</returns>
[MethodImpl(TryInline)]
public bool TryRemove(T pooledObject)
{
for (var i = 0; i < _pooledObjects.Length; i++)
{
var item = _pooledObjects[i];
if (item != null && item == pooledObject && Interlocked.CompareExchange(ref _pooledObjects[i], null, item) == item)
{
return true;
}
}
return false;
}
}
}
16 changes: 12 additions & 4 deletions src/CodeProject.ObjectPool/ObjectPool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -245,14 +245,18 @@ void IObjectPoolHandle.ReturnObjectToPool(PooledObject objectToReturnToPool, boo

#endregion Pool Operations

#region Private Methods
#region Protected Methods

/// <summary>
/// Keeps track of last pooled object ID.
/// </summary>
private int _lastPooledObjectId;

private T CreatePooledObject()
/// <summary>
/// Creates a new pooled object, initializing its info.
/// </summary>
/// <returns>A new pooled object.</returns>
protected T CreatePooledObject()
{
if (Diagnostics.Enabled)
{
Expand All @@ -271,7 +275,11 @@ private T CreatePooledObject()
return newObject;
}

private void DestroyPooledObject(PooledObject objectToDestroy)
/// <summary>
/// Destroys given pooled object, disposing its resources.
/// </summary>
/// <param name="objectToDestroy">The pooled object that should be destroyed.</param>
protected void DestroyPooledObject(PooledObject objectToDestroy)
{
// Making sure that the object is only disposed once (in case of application shutting
// down and we don't control the order of the finalization).
Expand All @@ -293,6 +301,6 @@ private void DestroyPooledObject(PooledObject objectToDestroy)
GC.SuppressFinalize(objectToDestroy);
}

#endregion Private Methods
#endregion Protected Methods
}
}
4 changes: 4 additions & 0 deletions src/CodeProject.ObjectPool/PooledObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,10 @@ private void HandleReAddingToPool(bool reRegisterForFinalization)
protected override IEnumerable<KeyValuePair<string, object>> GetFormattingMembers()
{
yield return new KeyValuePair<string, object>(nameof(PooledObjectInfo.Id), PooledObjectInfo.Id);
if (PooledObjectInfo.Payload != null)
{
yield return new KeyValuePair<string, object>(nameof(PooledObjectInfo.Payload), PooledObjectInfo.Payload);
}
}

/// <summary>
Expand Down
56 changes: 55 additions & 1 deletion src/CodeProject.ObjectPool/TimedObjectPool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@

#if !(NETSTD10 || NETSTD11)

using System;
using System.Linq;
using System.Threading;

namespace CodeProject.ObjectPool
Expand All @@ -37,7 +39,59 @@ namespace CodeProject.ObjectPool
internal class TimedObjectPool<T> : ObjectPool<T>, ITimedObjectPool<T>
where T : PooledObject
{
private readonly Timer Timer;
private TimeSpan _timeout;
private Timer _timer;

public TimedObjectPool()
{
}

/// <summary>
/// When pooled objects have not been used for a time greater than <see cref="Timeout"/>,
/// then they will be destroyed by a cleaning task.
/// </summary>
public TimeSpan Timeout
{
get => _timeout;
set
{
_timeout = value;
UpdateTimeout();
}
}

/// <summary>
/// Updates the timer according to a new timeout.
/// </summary>
private void UpdateTimeout()
{
lock (this)
{
if (_timer != null)
{
// A timer already exists, simply change its period.
_timer.Change(_timeout, _timeout);
return;
}

_timer = new Timer(_ =>
{
// Local copy, since the buffer might change.
var items = PooledObjects.ToArray();

// All items which have been last used before following threshold will be destroyed.
var threshold = DateTime.UtcNow - _timeout;

foreach (var item in items)
{
if (item.PooledObjectInfo.Payload is DateTime lastUsage && lastUsage < threshold && PooledObjects.TryRemove(item))
{
DestroyPooledObject(item);
}
}
}, null, _timeout, _timeout);
}
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="10.0.1" />
<PackageReference Include="Newtonsoft.Json" Version="10.0.2" />
<PackageReference Include="NLipsum" Version="1.0.1" />
<PackageReference Include="NUnit" Version="3.6.1" />
<PackageReference Include="NUnitLite" Version="3.6.1" />
Expand Down

0 comments on commit 84dffc8

Please sign in to comment.