123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- 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.Now;
- }
- }
- 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.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();
- }
- }
- }
|