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

Commit

Permalink
add base on timer evictor,tmed validation pooled objects
Browse files Browse the repository at this point in the history
  • Loading branch information
ULiiAn committed Jun 29, 2017
1 parent 671d0ed commit 5026f22
Show file tree
Hide file tree
Showing 7 changed files with 245 additions and 3 deletions.
5 changes: 5 additions & 0 deletions src/CodeProject.ObjectPool/Core/PooledObjectInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ public sealed class PooledObjectInfo : IEquatable<PooledObjectInfo>
/// </summary>
internal IObjectPoolHandle Handle { get; set; }

/// <summary>
/// The number of times the object was borrowed
/// </summary>
public long BorrowCount{get; internal set; }

/// <summary>
/// Returns a string that represents the current object.
/// </summary>
Expand Down
17 changes: 16 additions & 1 deletion src/CodeProject.ObjectPool/Core/PooledObjectState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,21 @@ public enum PooledObjectState : byte
/// <summary>
/// The object has been disposed and cannot be used anymore.
/// </summary>
Disposed = 2
Disposed = 2,

/// <summary>
/// The object is outside the pool, waiting to validate.
/// </summary>
Validating = 4,

/// <summary>
/// The object is outside the pool,waiting to be used.
/// </summary>
ValidateSuccess = 8,

/// <summary>
/// The object is outside the pool,waiting to destory.
/// </summary>
ValidateFail = 16
}
}
29 changes: 29 additions & 0 deletions src/CodeProject.ObjectPool/EvictionConfig.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright (c) GZNB. All rights reserved.

using System;
using System.Collections.Generic;
using System.Text;

namespace CodeProject.ObjectPool
{
/// <summary>
/// Eviction Config Infomation
/// </summary>
public class EvictionConfig
{
/// <summary>
/// Eviction Is Enable default is false
/// </summary>
public bool Enable { get; set; } = false;

/// <summary>
/// Timer delay time default is zero
/// </summary>
public TimeSpan Delay { get; set; } = TimeSpan.Zero;

/// <summary>
/// Timer period default is one minute
/// </summary>
public TimeSpan Period { get; set; } = TimeSpan.FromMinutes(1);
}
}
118 changes: 118 additions & 0 deletions src/CodeProject.ObjectPool/EvictorTimer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
// Copyright (c) GZNB. All rights reserved.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;

#if !NET35
using CodeProject.ObjectPool.Logging;
#endif


namespace CodeProject.ObjectPool
{
#if !NETSTD10
public class EvictorTimer : IEvictionTimer, IDisposable
{
#if !NET35
private static readonly ILog Log = LogProvider.GetLogger(typeof(EvictorTimer));
#endif
private Dictionary<Action, Timer> _actionMap;
private volatile bool _disposed;

public EvictorTimer()
{
this._actionMap = new Dictionary<Action, Timer>();
}

/// <summary>执行与释放或重置非托管资源关联的应用程序定义的任务。</summary>
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}

/// <summary>
/// Add Eviction action
/// </summary>
/// <param name="action">eviction action</param>
/// <param name="delay">delay time</param>
/// <param name="period">period</param>
public void Schedule(Action action, TimeSpan delay, TimeSpan period)
{
this.ThrowIfDisposed();
if (action == null)
{
return;
}
lock (typeof(EvictorTimer))
{
#if!NET35
Action piplineAction = () => Log.Debug("Begin Schedule Evictor");
piplineAction += action;
piplineAction += () => Log.Debug("End Schedule Evictor");
action = piplineAction;
#endif
if (this._actionMap.TryGetValue(action, out Timer timer))
{
timer.Change(delay, period);
}
else
{
var t = new Timer(state => action(), null, delay, period);
this._actionMap[action] = t;
}
}
}

/// <summary>
/// Cancle Action
/// </summary>
/// <param name="task"></param>
public void Cancel(Action task)
{
this.ThrowIfDisposed();
lock (typeof(EvictorTimer))
{
if (this._actionMap.TryGetValue(task, out Timer timer))
{
this._actionMap.Remove(task);
timer.Dispose();
}
}
}

private void ThrowIfDisposed()
{
if (this._disposed)
{
throw new ObjectDisposedException(this.GetType().FullName);
}
}

~EvictorTimer()
{
this.Dispose(false);
}

protected virtual void Dispose(bool disposing)
{
if (!this._disposed)
{
this._disposed = true;
if (disposing)
{
Timer[] timers = this._actionMap?.Values.ToArray() ?? new Timer[0];
this._actionMap.Clear();
this._actionMap = null;
foreach (Timer t in timers)
{
t.Dispose();
}
}
}
}
}
#endif
}
26 changes: 26 additions & 0 deletions src/CodeProject.ObjectPool/IEvictionTimer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace CodeProject.ObjectPool
{
/// <summary>
/// Eviction Timer Interface
/// </summary>
public interface IEvictionTimer
{
/// <summary>
/// Add Eviction action
/// </summary>
/// <param name="action">eviction action</param>
/// <param name="delay">delay time</param>
/// <param name="period">period</param>
void Schedule(Action action, TimeSpan delay, TimeSpan period);

/// <summary>
/// Cancle Action
/// </summary>
/// <param name="task"></param>
void Cancel(Action task);
}
}
42 changes: 41 additions & 1 deletion src/CodeProject.ObjectPool/ObjectPool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public ObjectPool(Func<T> factoryMethod)
/// <exception cref="ArgumentOutOfRangeException">
/// <paramref name="maximumPoolSize"/> is less than or equal to zero.
/// </exception>
public ObjectPool(int maximumPoolSize, Func<T> factoryMethod)
public ObjectPool(int maximumPoolSize, Func<T> factoryMethod, IEvictionTimer timer = null, EvictionConfig evictionConfig = null)
{
// Preconditions
if (maximumPoolSize <= 0) throw new ArgumentOutOfRangeException(nameof(maximumPoolSize), ErrorMessages.NegativeOrZeroMaximumPoolSize);
Expand All @@ -90,6 +90,13 @@ public ObjectPool(int maximumPoolSize, Func<T> factoryMethod)

// Creating a new instance for the Diagnostics class.
Diagnostics = new ObjectPoolDiagnostics();


#if !NETSTD10
// Creating a new instance for the EvictorTimer class.
this._timer = timer ?? new EvictorTimer();
#endif
this.StartEvictor(evictionConfig);
}

#endregion C'tor and Initialization code
Expand Down Expand Up @@ -158,6 +165,32 @@ public int MaximumPoolSize

#region Pool Operations

/// <summary>
/// Start Evictor
/// </summary>
/// <param name="config"></param>
protected void StartEvictor(EvictionConfig config)
{
if (this._timer != null && config.Enable)
{
this._timer.Schedule(
() =>
{
if (this.PooledObjects.TryDequeue(out T pooledObject))
{
if (pooledObject.ValidateObject(PooledObjectValidationContext.Outbound))
{
pooledObject.PooledObjectInfo.State = PooledObjectState.Available;
}
else
{
this.DestroyPooledObject(pooledObject);
}
}
}, config.Delay, config.Period);
}
}

/// <summary>
/// Clears the pool and destroys each object stored inside it.
/// </summary>
Expand Down Expand Up @@ -197,8 +230,13 @@ public T GetObject()
// as available as soon as the object will return to the pool.
pooledObject.PooledObjectInfo.State = PooledObjectState.Reserved;

pooledObject.PooledObjectInfo.BorrowCount++;
return pooledObject;
}
else
{
this.DestroyPooledObject(pooledObject);
}
}
}

Expand Down Expand Up @@ -261,6 +299,8 @@ void IObjectPoolHandle.ReturnObjectToPool(PooledObject objectToReturnToPool, boo
/// </summary>
private int _lastPooledObjectId;

private IEvictionTimer _timer;

/// <summary>
/// Creates a new pooled object, initializing its info.
/// </summary>
Expand Down
11 changes: 10 additions & 1 deletion src/CodeProject.ObjectPool/PooledObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,18 @@ internal bool ValidateObject(PooledObjectValidationContext validationContext)
{
if (OnValidateObject != null)
{
this.PooledObjectInfo.State = PooledObjectState.Validating;
try
{
return OnValidateObject(validationContext);
bool verifyResult = OnValidateObject(validationContext);
if (verifyResult)
{
this.PooledObjectInfo.State = PooledObjectState.ValidateSuccess;
}
else
{
this.PooledObjectInfo.State = PooledObjectState.ValidateFail;
}
}
catch (Exception ex)
{
Expand Down

0 comments on commit 5026f22

Please sign in to comment.