Skip to content

Commit

Permalink
Initial code
Browse files Browse the repository at this point in the history
  • Loading branch information
Enderlook committed Nov 22, 2021
1 parent 5fbb721 commit 853148e
Show file tree
Hide file tree
Showing 9 changed files with 1,417 additions and 0 deletions.
25 changes: 25 additions & 0 deletions Net Pools.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.31829.152
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Net Pools", "Net Pools\Net Pools.csproj", "{009D3D36-FB90-4318-B3FE-85BA53527D31}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{009D3D36-FB90-4318-B3FE-85BA53527D31}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{009D3D36-FB90-4318-B3FE-85BA53527D31}.Debug|Any CPU.Build.0 = Debug|Any CPU
{009D3D36-FB90-4318-B3FE-85BA53527D31}.Release|Any CPU.ActiveCfg = Release|Any CPU
{009D3D36-FB90-4318-B3FE-85BA53527D31}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {9D6637E5-BE56-4BE9-A652-6095FCF8FACB}
EndGlobalSection
EndGlobal
24 changes: 24 additions & 0 deletions Net Pools/Net Pools.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>netstandard2.0;netstandard2.1;net5;net6</TargetFrameworks>
<OutputType>Library</OutputType>
<PackageId>Enderlook.Pools</PackageId>
<AssemblyName>Enderlook.Pools</AssemblyName>
<RootNamespace>Enderlook.Pools</RootNamespace>
<Authors>Enderlook</Authors>
<Product>Enderlook.Pools</Product>
<RepositoryUrl>https://github.com/Enderlook/Net-Pools</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<Version>0.1.0</Version>
<LangVersion>10</LangVersion>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0' or '$(TargetFramework)' == 'netstandard2.1'">
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.5.3" />
</ItemGroup>

</Project>
445 changes: 445 additions & 0 deletions Net Pools/src/DynamicObjectPool.cs

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions Net Pools/src/NetStandard2.0.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#if !(NETSTANDARD2_1_OR_GREATER || NET5_0_OR_GREATER)
namespace System.Diagnostics.CodeAnalysis
{
[AttributeUsage(AttributeTargets.Method, Inherited = false)]
internal sealed class DoesNotReturnAttribute : Attribute { }
}
#endif
47 changes: 47 additions & 0 deletions Net Pools/src/ObjectPool.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using System.Runtime.CompilerServices;

namespace Enderlook.Pools
{
/// <summary>
/// Represent a pool of objects.
/// </summary>
/// <typeparam name="T">Type of object to pool</typeparam>
public abstract class ObjectPool<T> where T : class
{
/// <summary>
/// Retrieves a shared <see cref="ObjectPool{T}"/> instance.
/// </summary>
public static ObjectPool<T> Shared {
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => ThreadLocalOverPerCoreLockedStacksObjectPool<T>.Singlenton;
}

/// <summary>
/// Gets an approximate count of the objects stored in the pool.<br/>
/// This value is not accurate and may be lower or higher than the actual count.<br/>
/// This is primary used for debugging purposes.
/// </summary>
/// <returns>Approximate count of elements in the pool.</returns>
public abstract int ApproximateCount();

/// <summary>
/// Rent an element from the pool.<br/>
/// If the pool is empty, instantiate a new element.
/// </summary>
/// <returns>Rented element.</returns>
public abstract T Rent();

/// <summary>
/// Return an element to the pool.<br/>
/// If the pool is full, it's an implementation detail whenever the object is free or the pool is resized.<br/>
/// If <paramref name="obj"/> is <see langword="null"/>, it's an implementation detail whenever it throws an exception or ignores.
/// </summary>
public abstract void Return(T obj);

/// <summary>
/// Trim the content of the pool.
/// </summary>
/// <param name="force">If <see langword="true"/>, the pool is forced to clear all elements inside. Otherwise, the pool may only clear partially or not clear at all if the heuristic says so.</param>
public abstract void Trim(bool force = false);
}
}
54 changes: 54 additions & 0 deletions Net Pools/src/ObjectPoolHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
using System;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;

namespace Enderlook.Pools
{
internal static class ObjectPoolHelper<T> where T : class
{
public static readonly Func<T> Factory;

static ObjectPoolHelper()
{
// TODO: In .NET 7 Activator.CreateFactory<T>() may be added https://github.com/dotnet/runtime/issues/36194.

ConstructorInfo? constructor = typeof(T).GetConstructor(Type.EmptyTypes);
if (constructor is null)
{
Factory = () => throw new MissingMethodException($"No parameterless constructor defined for type '{typeof(T)}'.");
return;
}

switch (Utilities.DynamicCompilationMode)
{
case Utilities.SystemLinqExpressions:
Factory = Expression.Lambda<Func<T>>(Expression.New(typeof(T)), Array.Empty<ParameterExpression>()).Compile();
break;

#if NETSTANDARD2_1_OR_GREATER || NET5_0_OR_GREATER
case Utilities.SystemReflectionEmitDynamicMethod:

DynamicMethod dynamicMethod = new DynamicMethod("Instantiate", typeof(T), Type.EmptyTypes);
ILGenerator generator = dynamicMethod.GetILGenerator();
generator.Emit(OpCodes.Newobj, constructor);
generator.Emit(OpCodes.Ret);
#if NET5_0_OR_GREATER
Factory = dynamicMethod.CreateDelegate<Func<T>>();
#else
Factory = (Func<T>)dynamicMethod.CreateDelegate(typeof(Func<T>));
#endif
break;
#endif
default:
Factory = () => Activator.CreateInstance<T>();
break;
}
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T Create()
=> Utilities.DynamicCompilationMode == Utilities.DisabledDynamicCompilation ? Activator.CreateInstance<T>() : Factory();
}
}
7 changes: 7 additions & 0 deletions Net Pools/src/ObjectWrapper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Enderlook.Pools
{
internal struct ObjectWrapper<T> // Prevent runtime covariant checks on array access.
{
public T Value;
}
}
Loading

0 comments on commit 853148e

Please sign in to comment.