using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using Best.HTTP.Shared.PlatformSupport.Threading;
namespace Best.HTTP.Shared.PlatformSupport.Text
{
///
/// Implements pooling logic for instances.
///
[Best.HTTP.Shared.PlatformSupport.IL2CPP.Il2CppEagerStaticClassConstructionAttribute]
public static class StringBuilderPool
{
///
/// Setting this property to false the pooling mechanism can be disabled.
///
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;
///
/// Buffer entries that released back to the pool and older than this value are moved when next maintenance is triggered.
///
public static TimeSpan RemoveOlderThan = TimeSpan.FromSeconds(10);
///
/// How often pool maintenance must run.
///
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.Now;
}
}
private static List pooledBuilders = new List();
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.Now;
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();
}
}
}