- Initial commit
This commit is contained in:
147
Runtime/Shared/PlatformSupport/Text/StringBuilderPool.cs
Normal file
147
Runtime/Shared/PlatformSupport/Text/StringBuilderPool.cs
Normal file
@ -0,0 +1,147 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
||||
using Best.HTTP.Shared.PlatformSupport.Threading;
|
||||
|
||||
namespace Best.HTTP.Shared.PlatformSupport.Text
|
||||
{
|
||||
/// <summary>
|
||||
/// Implements pooling logic for <see cref="StringBuilder"/> instances.
|
||||
/// </summary>
|
||||
[Best.HTTP.Shared.PlatformSupport.IL2CPP.Il2CppEagerStaticClassConstructionAttribute]
|
||||
public static class StringBuilderPool
|
||||
{
|
||||
/// <summary>
|
||||
/// Setting this property to false the pooling mechanism can be disabled.
|
||||
/// </summary>
|
||||
public static bool IsEnabled
|
||||
{
|
||||
get { return _isEnabled; }
|
||||
set
|
||||
{
|
||||
_isEnabled = value;
|
||||
|
||||
// When set to non-enabled remove all stored entries
|
||||
if (!_isEnabled)
|
||||
Clear();
|
||||
}
|
||||
}
|
||||
private static volatile bool _isEnabled = true;
|
||||
|
||||
/// <summary>
|
||||
/// Buffer entries that released back to the pool and older than this value are moved when next maintenance is triggered.
|
||||
/// </summary>
|
||||
public static TimeSpan RemoveOlderThan = TimeSpan.FromSeconds(10);
|
||||
|
||||
/// <summary>
|
||||
/// How often pool maintenance must run.
|
||||
/// </summary>
|
||||
public static TimeSpan RunMaintenanceEvery = TimeSpan.FromSeconds(5);
|
||||
|
||||
private static DateTime lastMaintenance = DateTime.MinValue;
|
||||
|
||||
private readonly static ReaderWriterLockSlim rwLock = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion);
|
||||
|
||||
struct BuilderShelf
|
||||
{
|
||||
public StringBuilder builder;
|
||||
public DateTime released;
|
||||
|
||||
public BuilderShelf(StringBuilder sb)
|
||||
{
|
||||
this.builder = sb;
|
||||
this.released = DateTime.UtcNow;
|
||||
}
|
||||
}
|
||||
|
||||
private static List<BuilderShelf> pooledBuilders = new List<BuilderShelf>();
|
||||
|
||||
public static StringBuilder Get(int lengthHint)
|
||||
{
|
||||
if (!_isEnabled)
|
||||
return new StringBuilder(lengthHint);
|
||||
|
||||
using (new WriteLock(rwLock))
|
||||
{
|
||||
for (int i = pooledBuilders.Count - 1; i >= 0; i--)
|
||||
{
|
||||
BuilderShelf shelf = pooledBuilders[i];
|
||||
if (shelf.builder.Capacity >= lengthHint)
|
||||
{
|
||||
pooledBuilders.RemoveAt(i);
|
||||
return shelf.builder;
|
||||
}
|
||||
}
|
||||
|
||||
// no builder found with lengthHint, take the first available
|
||||
if (pooledBuilders.Count > 0)
|
||||
{
|
||||
BuilderShelf shelf = pooledBuilders[pooledBuilders.Count - 1];
|
||||
pooledBuilders.RemoveAt(pooledBuilders.Count - 1);
|
||||
return shelf.builder;
|
||||
}
|
||||
}
|
||||
|
||||
return new StringBuilder(lengthHint);
|
||||
}
|
||||
|
||||
public static void Release(StringBuilder builder)
|
||||
{
|
||||
if (builder == null)
|
||||
return;
|
||||
|
||||
if (!_isEnabled)
|
||||
return;
|
||||
|
||||
builder.Clear();
|
||||
|
||||
using (new WriteLock(rwLock))
|
||||
pooledBuilders.Add(new BuilderShelf(builder));
|
||||
}
|
||||
|
||||
public static string ReleaseAndGrab(StringBuilder builder)
|
||||
{
|
||||
if (builder == null)
|
||||
return null;
|
||||
|
||||
var result = builder.ToString();
|
||||
if (!_isEnabled)
|
||||
return result;
|
||||
|
||||
builder.Clear();
|
||||
|
||||
using (new WriteLock(rwLock))
|
||||
pooledBuilders.Add(new BuilderShelf(builder));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static void Maintain()
|
||||
{
|
||||
DateTime now = DateTime.UtcNow;
|
||||
if (!_isEnabled || lastMaintenance + RunMaintenanceEvery > now)
|
||||
return;
|
||||
lastMaintenance = now;
|
||||
|
||||
DateTime olderThan = now - RemoveOlderThan;
|
||||
using (new WriteLock(rwLock))
|
||||
{
|
||||
for (int i = 0; i < pooledBuilders.Count; i++)
|
||||
{
|
||||
BuilderShelf shelf = pooledBuilders[i];
|
||||
|
||||
if (shelf.released < olderThan)
|
||||
pooledBuilders.RemoveAt(i--);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void Clear()
|
||||
{
|
||||
using (new WriteLock(rwLock))
|
||||
pooledBuilders.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user