123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345 |
- using System;
- using System.Collections;
- using System.Collections.Concurrent;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading;
- namespace SuperSocket.Common
- {
- /// <summary>
- /// The pool information class
- /// </summary>
- public interface IPoolInfo
- {
- /// <summary>
- /// Gets the min size of the pool.
- /// </summary>
- /// <value>
- /// The min size of the pool.
- /// </value>
- int MinPoolSize { get; }
- /// <summary>
- /// Gets the max size of the pool.
- /// </summary>
- /// <value>
- /// The max size of the pool.
- /// </value>
- int MaxPoolSize { get; }
- /// <summary>
- /// Gets the avialable items count.
- /// </summary>
- /// <value>
- /// The avialable items count.
- /// </value>
- int AvialableItemsCount { get; }
- /// <summary>
- /// Gets the total items count, include items in the pool and outside the pool.
- /// </summary>
- /// <value>
- /// The total items count.
- /// </value>
- int TotalItemsCount { get; }
- }
- /// <summary>
- /// The basic interface of smart pool
- /// </summary>
- /// <typeparam name="T"></typeparam>
- public interface ISmartPool<T> : IPoolInfo
- {
- /// <summary>
- /// Initializes the specified min pool size.
- /// </summary>
- /// <param name="minPoolSize">The min size of the pool.</param>
- /// <param name="maxPoolSize">The max size of the pool.</param>
- /// <param name="sourceCreator">The source creator.</param>
- /// <returns></returns>
- void Initialize(int minPoolSize, int maxPoolSize, ISmartPoolSourceCreator<T> sourceCreator);
- /// <summary>
- /// Pushes the specified item into the pool.
- /// </summary>
- /// <param name="item">The item.</param>
- void Push(T item);
- /// <summary>
- /// Tries to get one item from the pool.
- /// </summary>
- /// <param name="item">The item.</param>
- /// <returns></returns>
- bool TryGet(out T item);
- }
- /// <summary>
- /// ISmartPoolSource
- /// </summary>
- public interface ISmartPoolSource
- {
- /// <summary>
- /// Gets the count.
- /// </summary>
- /// <value>
- /// The count.
- /// </value>
- int Count { get; }
- }
- /// <summary>
- /// SmartPoolSource
- /// </summary>
- public class SmartPoolSource : ISmartPoolSource
- {
- /// <summary>
- /// Initializes a new instance of the <see cref="SmartPoolSource" /> class.
- /// </summary>
- /// <param name="source">The source.</param>
- /// <param name="itemsCount">The items count.</param>
- public SmartPoolSource(object source, int itemsCount)
- {
- Source = source;
- Count = itemsCount;
- }
- /// <summary>
- /// Gets the source.
- /// </summary>
- /// <value>
- /// The source.
- /// </value>
- public object Source { get; private set; }
- /// <summary>
- /// Gets the count.
- /// </summary>
- /// <value>
- /// The count.
- /// </value>
- public int Count { get; private set; }
- }
- /// <summary>
- /// ISmartPoolSourceCreator
- /// </summary>
- /// <typeparam name="T"></typeparam>
- public interface ISmartPoolSourceCreator<T>
- {
- /// <summary>
- /// Creates the specified size.
- /// </summary>
- /// <param name="size">The size.</param>
- /// <param name="poolItems">The pool items.</param>
- /// <returns></returns>
- ISmartPoolSource Create(int size, out T[] poolItems);
- }
- /// <summary>
- /// The smart pool
- /// </summary>
- /// <typeparam name="T"></typeparam>
- public class SmartPool<T> : ISmartPool<T>
- {
- private ConcurrentStack<T> m_GlobalStack;
- private ISmartPoolSource[] m_ItemsSource;
- private int m_CurrentSourceCount;
- private ISmartPoolSourceCreator<T> m_SourceCreator;
- private int m_MinPoolSize;
- /// <summary>
- /// Gets the size of the min pool.
- /// </summary>
- /// <value>
- /// The size of the min pool.
- /// </value>
- public int MinPoolSize
- {
- get
- {
- return m_MinPoolSize;
- }
- }
- private int m_MaxPoolSize;
- /// <summary>
- /// Gets the size of the max pool.
- /// </summary>
- /// <value>
- /// The size of the max pool.
- /// </value>
- public int MaxPoolSize
- {
- get
- {
- return m_MaxPoolSize;
- }
- }
- /// <summary>
- /// Gets the avialable items count.
- /// </summary>
- /// <value>
- /// The avialable items count.
- /// </value>
- public int AvialableItemsCount
- {
- get
- {
- return m_GlobalStack.Count;
- }
- }
- private int m_TotalItemsCount;
- /// <summary>
- /// Gets the total items count, include items in the pool and outside the pool.
- /// </summary>
- /// <value>
- /// The total items count.
- /// </value>
- public int TotalItemsCount
- {
- get { return m_TotalItemsCount; }
- }
- /// <summary>
- /// Initializes the specified min and max pool size.
- /// </summary>
- /// <param name="minPoolSize">The min size of the pool.</param>
- /// <param name="maxPoolSize">The max size of the pool.</param>
- /// <param name="sourceCreator">The source creator.</param>
- public void Initialize(int minPoolSize, int maxPoolSize, ISmartPoolSourceCreator<T> sourceCreator)
- {
- m_MinPoolSize = minPoolSize;
- m_MaxPoolSize = maxPoolSize;
- m_SourceCreator = sourceCreator;
- m_GlobalStack = new ConcurrentStack<T>();
- var n = 0;
- if (minPoolSize != maxPoolSize)
- {
- var currentValue = minPoolSize;
- while (true)
- {
- n++;
- var thisValue = currentValue * 2;
- if (thisValue >= maxPoolSize)
- break;
- currentValue = thisValue;
- }
- }
- m_ItemsSource = new ISmartPoolSource[n + 1];
- T[] items;
- m_ItemsSource[0] = sourceCreator.Create(minPoolSize, out items);
- m_CurrentSourceCount = 1;
- for (var i = 0; i < items.Length; i++)
- {
- m_GlobalStack.Push(items[i]);
- }
- m_TotalItemsCount = m_MinPoolSize;
- }
- private int m_IsIncreasing = 0;
- /// <summary>
- /// Pushes the specified item into the pool.
- /// </summary>
- /// <param name="item">The item.</param>
- public void Push(T item)
- {
- m_GlobalStack.Push(item);
- }
- bool TryPopWithWait(out T item, int waitTicks)
- {
- var spinWait = new SpinWait();
- while (true)
- {
- spinWait.SpinOnce();
- if (m_GlobalStack.TryPop(out item))
- return true;
- if (spinWait.Count >= waitTicks)
- {
- return false;
- }
- }
- }
- /// <summary>
- /// Tries to get one item from the pool.
- /// </summary>
- /// <param name="item">The item.</param>
- /// <returns></returns>
- /// <exception cref="System.NotImplementedException"></exception>
- public bool TryGet(out T item)
- {
- if (m_GlobalStack.TryPop(out item))
- return true;
- var currentSourceCount = m_CurrentSourceCount;
- if (currentSourceCount >= m_ItemsSource.Length)
- {
- return TryPopWithWait(out item, 100);
- }
- var isIncreasing = m_IsIncreasing;
- if (isIncreasing == 1)
- return TryPopWithWait(out item, 100);
- if (Interlocked.CompareExchange(ref m_IsIncreasing, 1, isIncreasing) != isIncreasing)
- return TryPopWithWait(out item, 100);
- IncreaseCapacity();
- m_IsIncreasing = 0;
- if (!m_GlobalStack.TryPop(out item))
- {
- return false;
- }
- return true;
- }
- private void IncreaseCapacity()
- {
- var newItemsCount = Math.Min(m_TotalItemsCount, m_MaxPoolSize - m_TotalItemsCount);
- T[] items;
- m_ItemsSource[m_CurrentSourceCount++] = m_SourceCreator.Create(newItemsCount, out items);
- m_TotalItemsCount += newItemsCount;
- for (var i = 0; i < items.Length; i++)
- {
- m_GlobalStack.Push(items[i]);
- }
- }
- }
- }
|