LinkedPool.cs 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. using System.Runtime.CompilerServices;
  2. using System.Runtime.InteropServices;
  3. using System.Threading;
  4. namespace LitMotion.Collections
  5. {
  6. /// <summary>
  7. /// Thread-safe linked list object pool
  8. /// </summary>
  9. /// <typeparam name="T"></typeparam>
  10. [StructLayout(LayoutKind.Auto)]
  11. public struct LinkedPool<T> where T : class, ILinkedPoolNode<T>
  12. {
  13. static readonly int MaxPoolSize = int.MaxValue;
  14. int gate;
  15. int size;
  16. T root;
  17. public readonly int Size => size;
  18. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  19. public bool TryPop(out T result)
  20. {
  21. if (Interlocked.CompareExchange(ref gate, 1, 0) == 0)
  22. {
  23. var v = root;
  24. if (v != null)
  25. {
  26. ref var nextNode = ref v.NextNode;
  27. root = nextNode;
  28. nextNode = null;
  29. size--;
  30. result = v;
  31. Volatile.Write(ref gate, 0);
  32. return true;
  33. }
  34. Volatile.Write(ref gate, 0);
  35. }
  36. result = default;
  37. return false;
  38. }
  39. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  40. public bool TryPush(T item)
  41. {
  42. if (Interlocked.CompareExchange(ref gate, 1, 0) == 0)
  43. {
  44. if (size < MaxPoolSize)
  45. {
  46. item.NextNode = root;
  47. root = item;
  48. size++;
  49. Volatile.Write(ref gate, 0);
  50. return true;
  51. }
  52. else
  53. {
  54. Volatile.Write(ref gate, 0);
  55. }
  56. }
  57. return false;
  58. }
  59. }
  60. }