Skip to content

Commit

Permalink
Merge pull request #41 from faustodavid/DocumentCode
Browse files Browse the repository at this point in the history
Create Release
  • Loading branch information
faustodavid authored Jan 18, 2020
2 parents c42f5f9 + 3b89594 commit af148f8
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 11 deletions.
30 changes: 28 additions & 2 deletions src/ListPool/ListPool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@

namespace ListPool
{
/// <summary>
/// Overhead free implementation of IList using ArrayPool.
/// With overhead being the class itself regardless the size of the underlying array.
/// </summary>
/// <typeparam name="TSource"></typeparam>
public sealed class ListPool<TSource> : IList<TSource>, IList, IReadOnlyList<TSource>, IDisposable,
IValueEnumerable<TSource>

Expand All @@ -18,16 +23,28 @@ public sealed class ListPool<TSource> : IList<TSource>, IList, IReadOnlyList<TSo
[NonSerialized]
private object? _syncRoot;

/// <summary>
/// Construct ListPool with default capacity.
/// We recommend to indicate the required capacity in front to avoid regrowing as much as possible.
/// </summary>
public ListPool()
{
_bufferOwner = new BufferOwner<TSource>(MinimumCapacity);
}

public ListPool(int length)
/// <summary>
/// Construct ListPool with the indicated capacity.
/// </summary>
/// <param name="capacity">Required initial capacity</param>
public ListPool(int capacity)
{
_bufferOwner = new BufferOwner<TSource>(length < MinimumCapacity ? MinimumCapacity : length);
_bufferOwner = new BufferOwner<TSource>(capacity < MinimumCapacity ? MinimumCapacity : capacity);
}

/// <summary>
/// Construct ListPool from the given source.
/// </summary>
/// <param name="source"></param>
public ListPool(IEnumerable<TSource> source)
{
if (source is ICollection<TSource> collection)
Expand All @@ -49,8 +66,14 @@ public ListPool(IEnumerable<TSource> source)
}
}

/// <summary>
/// Capacity of the underlying array.
/// </summary>
public int Capacity => _bufferOwner.Buffer.Length;

/// <summary>
/// Returns underlying array to the pool
/// </summary>
public void Dispose()
{
_bufferOwner.Dispose();
Expand Down Expand Up @@ -172,6 +195,9 @@ object IList.this[int index]
}
}

/// <summary>
/// Count of items added.
/// </summary>
public int Count { get; private set; }

public bool IsReadOnly => false;
Expand Down
8 changes: 5 additions & 3 deletions src/ListPool/ListPool.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,17 @@
<Title>ListPool</Title>
<AssemblyName>ListPool</AssemblyName>
<PackageId>ListPool</PackageId>
<Description>ListPool is an optimized allocation free implementation of IList using ArrayPool.</Description>
<Description>ListPool and ValueListPool are an optimized allocation free implementations of IList using ArrayPool.</Description>
<PackageTags>ASP.NET;List;System.Buffers;ArrayPool;ListPool;Performance</PackageTags>
<RepositoryUrl>https://github.com/faustodavid/ListPool</RepositoryUrl>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<PackageVersion>2.1.0</PackageVersion>
<PackageVersion>2.2.0</PackageVersion>
<PackageReleaseNotes>
Changelog:
* Rename ListPoolValue to ValueListPool
* Improve performance of ValueListPool by removing buffer checks.Now is required to avoid parametless constructor for ValueListPool.
* Add support for span and memory
* Add method AddRange

ListPool is the general use of the implementation. ValueListPool is the zero heap allocations implementation. Note, because it is a struct it is passed by value, not by reference.
</PackageReleaseNotes>
Expand Down
34 changes: 28 additions & 6 deletions src/ListPool/ValueListPool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,26 @@

namespace ListPool
{
/// <summary>
/// High-performance implementation of IList with zero heap allocations.
/// IMPORTANT:Do not create ValueListPool without indicating a constructor.
/// Otherwise it wont work.
/// </summary>
/// <typeparam name="TSource"></typeparam>
public struct ValueListPool<TSource> : IList<TSource>, IList, IReadOnlyList<TSource>, IDisposable,
IValueEnumerable<TSource>

{
public readonly int Capacity =>_bufferOwner.Buffer.Length;
/// <summary>
/// Capacity of the underlying array.
/// </summary>
public readonly int Capacity => _bufferOwner.Buffer.Length;

/// <summary>
/// Count of items added.
/// </summary>
public int Count { get; private set; }

public readonly bool IsReadOnly => false;
public readonly Span<TSource> AsSpan() => _bufferOwner.Buffer.AsSpan(0, Count);
public readonly Memory<TSource> AsMemory() => _bufferOwner.Buffer.AsMemory(0, Count);
Expand All @@ -40,13 +54,21 @@ object ICollection.SyncRoot
}
}

public ValueListPool(int length)
/// <summary>
/// Construct ValueListPool with the indicated capacity.
/// </summary>
/// <param name="capacity">Required initial capacity</param>
public ValueListPool(int capacity)
{
_syncRoot = null;
_bufferOwner = new BufferOwner<TSource>(length < MinimumCapacity ? MinimumCapacity : length);
_bufferOwner = new BufferOwner<TSource>(capacity < MinimumCapacity ? MinimumCapacity : capacity);
Count = 0;
}

/// <summary>
/// Construct ValueListPool from the given source.
/// </summary>
/// <param name="source"></param>
public ValueListPool(IEnumerable<TSource> source)
{
_syncRoot = null;
Expand Down Expand Up @@ -86,7 +108,7 @@ int IList.Add(object item)
}
else
{
throw new ArgumentException($"Wrong type. Expected {typeof(TSource)}, actual: '{item}'.", nameof(item));
throw new ArgumentException($"Wrong type. Expected {typeof(TSource)}, actual: '{item}'.", nameof(item));
}

return Count - 1;
Expand Down Expand Up @@ -145,7 +167,7 @@ bool IList.Contains(object item)
return Contains(itemAsTSource);
}

throw new ArgumentException($"Wrong type. Expected {typeof(TSource)}, actual: '{item}'.", nameof(item));
throw new ArgumentException($"Wrong type. Expected {typeof(TSource)}, actual: '{item}'.", nameof(item));
}

int IList.IndexOf(object item)
Expand All @@ -155,7 +177,7 @@ int IList.IndexOf(object item)
return IndexOf(itemAsTSource);
}

throw new ArgumentException($"Wrong type. Expected {typeof(TSource)}, actual: '{item}'.", nameof(item));
throw new ArgumentException($"Wrong type. Expected {typeof(TSource)}, actual: '{item}'.", nameof(item));
}

void IList.Remove(object item)
Expand Down

0 comments on commit af148f8

Please sign in to comment.