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

Commit

Permalink
pooled object info
Browse files Browse the repository at this point in the history
  • Loading branch information
pomma89 committed Mar 29, 2017
1 parent 0a73269 commit df8e52e
Show file tree
Hide file tree
Showing 9 changed files with 49 additions and 48 deletions.
1 change: 1 addition & 0 deletions src/CodeProject.ObjectPool/CodeProject.ObjectPool.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

<PropertyGroup>
<PackageId>CodeProject.ObjectPool</PackageId>
<Title>Generic and concurrent Object Pool</Title>
<Summary>A generic, concurrent, portable and flexible Object Pool for the .NET Framework.</Summary>
<Description>$(Summary) It is completely based on the Code Project article of Ofir Makmal (http://goo.gl/4qig6T). Library is production ready and it is successfully working in real life systems. Original source code has been modified, in order to introduce a Parameterized Object Pool, already drafted by Ofir Makmal in the comments of the article. Moreover, a few unit tests have been added, in order to improve code reliability, and a lot of other small changes have also been applied. Of course, all modified source code is freely available at the project URL of this package. Many thanks to Ofir Makmal for his great work.</Description>
<Authors>Ofir Makmal &lt;ofir.makmal@gmail.com&gt;;Alessio Parma &lt;alessio.parma@gmail.com&gt;</Authors>
Expand Down
19 changes: 16 additions & 3 deletions src/CodeProject.ObjectPool/Core/PooledObjectInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,26 @@
namespace CodeProject.ObjectPool.Core
{
/// <summary>
/// Information about a specific <see cref="PooledObject"/>.
/// Core information about a specific <see cref="PooledObject"/>.
/// </summary>
public sealed class PooledObjectInfo
{
/// <summary>
/// The state.
/// An identifier which is unique inside the pool to which this object belongs. Moreover,
/// this identifier increases monotonically as new objects are created.
/// </summary>
public PooledObjectState State { get; set; }
public int Id { get; internal set; }

/// <summary>
/// Enumeration that is being managed by the pool to describe the object state - primary
/// used to void cases where the resources are being releases twice.
/// </summary>
public PooledObjectState State { get; internal set; }

/// <summary>
/// Internal action that is initialized by the pool while creating the object, this allows
/// that object to re-add itself back to the pool.
/// </summary>
internal IObjectPoolHandle Handle { get; set; }
}
}
14 changes: 7 additions & 7 deletions src/CodeProject.ObjectPool/ObjectPool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ public T GetObject()

// Change the state of the pooled object, marking it as reserved. We will mark it as
// available as soon as the object will return to the pool.
pooledObject.PooledObjectState = PooledObjectState.Reserved;
pooledObject.PooledObjectInfo.State = PooledObjectState.Reserved;

return pooledObject;
}
Expand Down Expand Up @@ -224,7 +224,7 @@ void IObjectPoolHandle.ReturnObjectToPool(PooledObject objectToReturnToPool, boo
}

// While adding the object back to the pool, we mark it as available.
returnedObject.PooledObjectState = PooledObjectState.Available;
returnedObject.PooledObjectInfo.State = PooledObjectState.Available;
}
else
{
Expand Down Expand Up @@ -340,17 +340,17 @@ private T CreatePooledObject()
var newObject = FactoryMethod?.Invoke() ?? Activator.CreateInstance<T>();

// Setting the 'return to pool' action and other properties in the newly created pooled object.
newObject.ObjectPoolHandle = this;
newObject.PooledObjectId = Interlocked.Increment(ref _lastPooledObjectId);
newObject.PooledObjectState = PooledObjectState.Available;
newObject.PooledObjectInfo.Id = Interlocked.Increment(ref _lastPooledObjectId);
newObject.PooledObjectInfo.State = PooledObjectState.Available;
newObject.PooledObjectInfo.Handle = this;
return newObject;
}

private 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).
if (objectToDestroy.PooledObjectState != PooledObjectState.Disposed)
if (objectToDestroy.PooledObjectInfo.State != PooledObjectState.Disposed)
{
if (Diagnostics.Enabled)
{
Expand All @@ -360,7 +360,7 @@ private void DestroyPooledObject(PooledObject objectToDestroy)
// Deterministically release object resources, nevermind the result, we are
// destroying the object.
objectToDestroy.ReleaseResources();
objectToDestroy.PooledObjectState = PooledObjectState.Disposed;
objectToDestroy.PooledObjectInfo.State = PooledObjectState.Disposed;
}

// The object is being destroyed, resources have been already released deterministically,
Expand Down
23 changes: 5 additions & 18 deletions src/CodeProject.ObjectPool/PooledObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,22 +36,9 @@ public abstract class PooledObject : IDisposable
#region Properties

/// <summary>
/// An identifier which is unique inside the pool to which this object belongs. Moreover,
/// this identifier increases monotonically as new objects are created.
/// Core information about this <see cref="PooledObject"/>.
/// </summary>
public int PooledObjectId { get; internal set; }

/// <summary>
/// Enumeration that is being managed by the pool to describe the object state - primary
/// used to void cases where the resources are being releases twice.
/// </summary>
public PooledObjectState PooledObjectState { get; internal set; }

/// <summary>
/// Internal action that is initialized by the pool while creating the object, this allows
/// that object to re-add itself back to the pool.
/// </summary>
internal IObjectPoolHandle ObjectPoolHandle { get; set; }
public PooledObjectInfo PooledObjectInfo { get; } = new PooledObjectInfo();

#endregion Properties

Expand Down Expand Up @@ -163,7 +150,7 @@ public void Dispose()
private void HandleReAddingToPool(bool reRegisterForFinalization)
{
// Only when the object is reserved it can be readded to the pool.
if (PooledObjectState == Core.PooledObjectState.Disposed || PooledObjectState == Core.PooledObjectState.Available)
if (PooledObjectInfo.State == PooledObjectState.Disposed || PooledObjectInfo.State == PooledObjectState.Available)
{
return;
}
Expand All @@ -172,7 +159,7 @@ private void HandleReAddingToPool(bool reRegisterForFinalization)
try
{
// Notifying the pool that this object is ready for re-adding to the pool.
ObjectPoolHandle.ReturnObjectToPool(this, reRegisterForFinalization);
PooledObjectInfo.Handle.ReturnObjectToPool(this, reRegisterForFinalization);
}
catch (Exception ex)
{
Expand All @@ -184,7 +171,7 @@ private void HandleReAddingToPool(bool reRegisterForFinalization)
#else
System.Diagnostics.Debug.Assert(ex != null); // Placeholder to avoid warnings
#endif
PooledObjectState = Core.PooledObjectState.Disposed;
PooledObjectInfo.State = PooledObjectState.Disposed;
ReleaseResources();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ protected override void OnResetState()
throw new CannotResetStateException($"Memory stream has already been disposed");
}

var memoryStreamPool = ObjectPoolHandle as IMemoryStreamPool;
var memoryStreamPool = PooledObjectInfo.Handle as IMemoryStreamPool;
if (_trackedMemoryStream.Capacity < memoryStreamPool.MinimumMemoryStreamCapacity)
{
throw new CannotResetStateException($"Memory stream capacity is {_trackedMemoryStream.Capacity}, while minimum required capacity is {memoryStreamPool.MinimumMemoryStreamCapacity}");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public PooledStringBuilder(int capacity)
/// </summary>
protected override void OnResetState()
{
var stringBuilderPool = ObjectPoolHandle as IStringBuilderPool;
var stringBuilderPool = PooledObjectInfo.Handle as IStringBuilderPool;
if (StringBuilder.Capacity > stringBuilderPool.MaximumStringBuilderCapacity)
{
throw new CannotResetStateException($"String builder capacity is {StringBuilder.Capacity}, while maximum allowed capacity is {stringBuilderPool.MaximumStringBuilderCapacity}");
Expand Down
12 changes: 6 additions & 6 deletions test/CodeProject.ObjectPool.UnitTests/ObjectPoolTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,8 @@ public void ShouldNotResetPooledObjectIdsWhenCleared()
var poA = pool.GetObject();
var poB = pool.GetObject();

poA.PooledObjectId.ShouldBe(1);
poB.PooledObjectId.ShouldBe(2);
poA.PooledObjectInfo.Id.ShouldBe(1);
poB.PooledObjectInfo.Id.ShouldBe(2);

poA.Dispose();
poB.Dispose();
Expand All @@ -125,7 +125,7 @@ public void ShouldNotResetPooledObjectIdsWhenCleared()

var poC = pool.GetObject();

poC.PooledObjectId.ShouldBe(3);
poC.PooledObjectInfo.Id.ShouldBe(3);
}

[Test]
Expand Down Expand Up @@ -230,7 +230,7 @@ public void PooledObjectStateShouldBecomeReservedWhenRetrievedFromThePool()

using (var obj = pool.GetObject())
{
obj.PooledObjectState.ShouldBe(PooledObjectState.Reserved);
obj.PooledObjectInfo.State.ShouldBe(PooledObjectState.Reserved);
}
}

Expand All @@ -244,7 +244,7 @@ public void PooledObjectStateShouldBecomeAvailableWhenReturnedToThePool()
{
}

obj.PooledObjectState.ShouldBe(PooledObjectState.Available);
obj.PooledObjectInfo.State.ShouldBe(PooledObjectState.Available);
}

[Test]
Expand All @@ -260,7 +260,7 @@ public void PooledObjectStateShouldBecomeDisposedWhenCannotReturnToThePool()
}

obj.Dispose();
obj.PooledObjectState.ShouldBe(PooledObjectState.Disposed);
obj.PooledObjectInfo.State.ShouldBe(PooledObjectState.Disposed);
}

#endregion Pooled object state
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -272,14 +272,14 @@ public void IdPropertyShouldNotChangeUsageAfterUsage()
int id;
using (var pms = _memoryStreamPool.GetObject())
{
id = pms.PooledObjectId;
id = pms.PooledObjectInfo.Id;
id.ShouldNotBe(0);
}

// Second usage is the same, pool uses a sort of stack, not a proper queue.
using (var pms = _memoryStreamPool.GetObject())
{
pms.PooledObjectId.ShouldBe(id);
pms.PooledObjectInfo.Id.ShouldBe(id);
}
}

Expand Down Expand Up @@ -325,15 +325,15 @@ public void ShouldNotClearPoolWhenMaxCapacityIsIncreased()
int initialId;
using (var pms = _memoryStreamPool.GetObject())
{
initialId = pms.PooledObjectId;
initialId = pms.PooledObjectInfo.Id;
}

initialId.ShouldBeGreaterThan(0);

_memoryStreamPool.MaximumMemoryStreamCapacity *= 2;
using (var pms = _memoryStreamPool.GetObject())
{
pms.PooledObjectId.ShouldBe(initialId);
pms.PooledObjectInfo.Id.ShouldBe(initialId);
}
}

Expand All @@ -343,15 +343,15 @@ public void ShouldClearPoolWhenMaxCapacityIsDecreased()
int initialId;
using (var pms = _memoryStreamPool.GetObject())
{
initialId = pms.PooledObjectId;
initialId = pms.PooledObjectInfo.Id;
}

initialId.ShouldBeGreaterThan(0);

_memoryStreamPool.MaximumMemoryStreamCapacity /= 2;
using (var pms = _memoryStreamPool.GetObject())
{
pms.PooledObjectId.ShouldBeGreaterThan(initialId);
pms.PooledObjectInfo.Id.ShouldBeGreaterThan(initialId);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,14 +100,14 @@ public void IdPropertyShouldNotChangeUsageAfterUsage()
int id;
using (var psb = _stringBuilderPool.GetObject())
{
id = psb.PooledObjectId;
id = psb.PooledObjectInfo.Id;
id.ShouldNotBe(0);
}

// Second usage is the same, pool uses a sort of stack, not a proper queue.
using (var psb = _stringBuilderPool.GetObject())
{
psb.PooledObjectId.ShouldBe(id);
psb.PooledObjectInfo.Id.ShouldBe(id);
}
}

Expand Down Expand Up @@ -198,15 +198,15 @@ public void ShouldNotClearPoolWhenMaxCapacityIsIncreased()
int initialId;
using (var psb = _stringBuilderPool.GetObject())
{
initialId = psb.PooledObjectId;
initialId = psb.PooledObjectInfo.Id;
}

initialId.ShouldBeGreaterThan(0);

_stringBuilderPool.MaximumStringBuilderCapacity *= 2;
using (var psb = _stringBuilderPool.GetObject())
{
psb.PooledObjectId.ShouldBe(initialId);
psb.PooledObjectInfo.Id.ShouldBe(initialId);
}
}

Expand All @@ -216,15 +216,15 @@ public void ShouldClearPoolWhenMaxCapacityIsDecreased()
int initialId;
using (var psb = _stringBuilderPool.GetObject())
{
initialId = psb.PooledObjectId;
initialId = psb.PooledObjectInfo.Id;
}

initialId.ShouldBeGreaterThan(0);

_stringBuilderPool.MaximumStringBuilderCapacity /= 2;
using (var psb = _stringBuilderPool.GetObject())
{
psb.PooledObjectId.ShouldBeGreaterThan(initialId);
psb.PooledObjectInfo.Id.ShouldBeGreaterThan(initialId);
}
}
}
Expand Down

0 comments on commit df8e52e

Please sign in to comment.