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

Commit

Permalink
moved buffer logic into dedicated class
Browse files Browse the repository at this point in the history
  • Loading branch information
pomma89 committed Apr 2, 2017
1 parent 6158e33 commit 21750fa
Show file tree
Hide file tree
Showing 3 changed files with 185 additions and 110 deletions.
141 changes: 141 additions & 0 deletions src/CodeProject.ObjectPool/Core/PooledObjectBuffer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
// File name: PooledObjectBuffer.cs
//
// Author(s): Alessio Parma <alessio.parma@gmail.com>
//
// The MIT License (MIT)
//
// Copyright (c) 2013-2018 Alessio Parma <alessio.parma@gmail.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
// associated documentation files (the "Software"), to deal in the Software without restriction,
// including without limitation the rights to use, copy, modify, merge, publish, distribute,
// sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// 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 OR COPYRIGHT HOLDERS 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.

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

namespace CodeProject.ObjectPool.Core
{
/// <summary>
/// A buffer into which pooled objects are stored. This buffer mostly behaves like a queue,
/// even if that behaviour is not stricly respected in order to maximize performance.
/// </summary>
/// <typeparam name="T">
/// The type of the object that which will be managed by the pool. The pooled object have to be
/// a sub-class of PooledObject.
/// </typeparam>
public sealed class PooledObjectBuffer<T>
where T : PooledObject
{
/// <summary>
/// The concurrent buffer containing pooled objects.
/// </summary>
private T[] _pooledObjects;

public int Capacity => _pooledObjects.Length;

public int Count
{
get
{
var count = 0;
for (var i = 0; i < _pooledObjects.Length; ++i)
{
if (_pooledObjects[i] != null)
{
count++;
}
}
return count;
}
}

/// <summary>
/// All objects currently stored inside the pool.
/// </summary>
protected IEnumerable<T> PooledObjects
{
get
{
for (var i = 0; i <= _pooledObjects.Length; ++i)
{
var item = _pooledObjects[i];
if (item != null)
{
yield return item;
}
}
}
}

public bool TryDequeue(out T pooledObject)
{
for (var i = 0; i < _pooledObjects.Length; i++)
{
var item = _pooledObjects[i];
if (item != null && Interlocked.CompareExchange(ref _pooledObjects[i], null, item) == item)
{
pooledObject = item;
return true;
}
}
pooledObject = null;
return false;
}

public bool TryEnqueue(T pooledObject)
{
for (var i = 0; i < _pooledObjects.Length; i++)
{
ref var item = ref _pooledObjects[i];
if (item == null && Interlocked.CompareExchange(ref item, pooledObject, null) == null)
{
return true;
}
}
return false;
}

public void ResizeBuffer(int newSize)
{
if (_pooledObjects == null)
{
_pooledObjects = new T[newSize];
return;
}

var currentSize = _pooledObjects.Length;
if (currentSize == newSize)
{
// Nothing to do.
return;
}

if (currentSize > newSize)
{
for (var i = newSize; i < currentSize; ++i)
{
ref var item = ref _pooledObjects[i];
if (item != null)
{
item.Dispose();
item = null;
}
}
}

Array.Resize(ref _pooledObjects, newSize);
}
}
}
125 changes: 15 additions & 110 deletions src/CodeProject.ObjectPool/ObjectPool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
using CodeProject.ObjectPool.Core;
using PommaLabs.Thrower;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;

Expand Down Expand Up @@ -60,21 +59,26 @@ public int MaximumPoolSize
{
get
{
return _pooledObjects.Length;
return _pooledObjects.Capacity;
}
set
{
// Preconditions
Raise.ArgumentOutOfRangeException.If(value < 1, nameof(value), ErrorMessages.NegativeOrZeroMaximumPoolSize);

ResizeBuffer(value);
_pooledObjects.ResizeBuffer(value);
}
}

/// <summary>
/// Gets the count of the objects currently in the pool.
/// </summary>
public int ObjectsInPoolCount => _pooledObjects.Count(x => x != null);
public int ObjectsInPoolCount => _pooledObjects.Count;

/// <summary>
/// The concurrent buffer containing pooled objects.
/// </summary>
protected PooledObjectBuffer<T> _pooledObjects { get; } = new PooledObjectBuffer<T>();

#endregion Public Properties

Expand Down Expand Up @@ -140,7 +144,7 @@ public ObjectPool(int maximumPoolSize, Func<T> factoryMethod)
~ObjectPool()
{
// The pool is going down, releasing the resources for all objects in pool.
ClearBuffer();
Clear();
}

#endregion Finalizer
Expand All @@ -153,7 +157,10 @@ public ObjectPool(int maximumPoolSize, Func<T> factoryMethod)
public void Clear()
{
// Destroy all objects.
ClearBuffer();
while (_pooledObjects.TryDequeue(out T dequeuedObjectToDestroy))
{
DestroyPooledObject(dequeuedObjectToDestroy);
}
}

/// <summary>
Expand All @@ -162,7 +169,7 @@ public void Clear()
/// <returns>A monitored object from the pool.</returns>
public T GetObject()
{
if (TryDequeue(out T pooledObject))
if (_pooledObjects.TryDequeue(out T pooledObject))
{
// Object found in pool.
if (Diagnostics.Enabled)
Expand Down Expand Up @@ -217,7 +224,7 @@ void IObjectPoolHandle.ReturnObjectToPool(PooledObject objectToReturnToPool, boo
}

// Trying to add the object back to the pool.
if (TryEnqueue(returnedObject))
if (_pooledObjects.TryEnqueue(returnedObject))
{
if (Diagnostics.Enabled)
{
Expand All @@ -241,108 +248,6 @@ void IObjectPoolHandle.ReturnObjectToPool(PooledObject objectToReturnToPool, boo

#endregion Pool Operations

#region Extensibility

/// <summary>
/// All objects currently stored inside the pool.
/// </summary>
protected IEnumerable<T> PooledObjects
{
get
{
for (var i = 0; i <= _pooledObjects.Length; ++i)
{
var item = _pooledObjects[i];
if (item != null)
{
yield return item;
}
}
}
}

#endregion Extensibility

#region Low-level Pooling

/// <summary>
/// The concurrent buffer containing pooled objects.
/// </summary>
private T[] _pooledObjects;

private void ClearBuffer()
{
if (_pooledObjects == null)
{
return;
}
while (TryDequeue(out T dequeuedObjectToDestroy))
{
DestroyPooledObject(dequeuedObjectToDestroy);
}
}

private bool TryDequeue(out T pooledObject)
{
for (var i = 0; i < _pooledObjects.Length; i++)
{
var item = _pooledObjects[i];
if (item != null && Interlocked.CompareExchange(ref _pooledObjects[i], null, item) == item)
{
pooledObject = item;
return true;
}
}
pooledObject = null;
return false;
}

private bool TryEnqueue(T pooledObject)
{
for (var i = 0; i < _pooledObjects.Length; i++)
{
ref var item = ref _pooledObjects[i];
if (item == null && Interlocked.CompareExchange(ref item, pooledObject, null) == null)
{
return true;
}
}
return false;
}

private void ResizeBuffer(int newSize)
{
if (_pooledObjects == null)
{
_pooledObjects = new T[newSize];
return;
}

var currentSize = _pooledObjects.Length;
if (currentSize == newSize)
{
// Nothing to do.
return;
}

if (currentSize > newSize)
{
for (var i = newSize; i < currentSize; ++i)
{
ref var item = ref _pooledObjects[i];
if (item != null)
{
item.Dispose();
item = null;
}
}
}

Array.Resize(ref _pooledObjects, newSize);
}

#endregion Low-level Pooling

#region Private Methods

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// File name: TimedObjectPool.cs
//
// Author(s): Alessio Parma <alessio.parma@gmail.com>
//
// The MIT License (MIT)
//
// Copyright (c) 2013-2018 Alessio Parma <alessio.parma@gmail.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
// associated documentation files (the "Software"), to deal in the Software without restriction,
// including without limitation the rights to use, copy, modify, merge, publish, distribute,
// sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// 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 OR COPYRIGHT HOLDERS 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.

namespace CodeProject.ObjectPool.Examples.Customizations
{
internal class TimedObjectPool
{
}
}

0 comments on commit 21750fa

Please sign in to comment.