AtomicCounterPool.cs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. using NetMQ.Core.Utils;
  2. using System;
  3. using System.Threading;
  4. namespace NetMQ
  5. {
  6. /// <summary>
  7. /// The IBufferPool interface specifies two methods: Take, and Return.
  8. /// These provide for taking atomic counters from a common pool, and returning them.
  9. /// </summary>
  10. public interface IAtomicCounterPool : IDisposable
  11. {
  12. /// <summary>
  13. /// Take an AtomicCounter from the pool.
  14. /// </summary>
  15. /// <returns>an atomic counter</returns>
  16. AtomicCounter Take();
  17. /// <summary>
  18. /// Return the given atomic counter to the common pool.
  19. /// </summary>
  20. /// <param name="counter">the atomic counter to return to the buffer-pool</param>
  21. void Return(AtomicCounter counter);
  22. }
  23. /// <summary>
  24. /// This simple implementation of <see cref="IAtomicCounterPool"/> does no pooling. Instead, it uses regular
  25. /// .NET memory management to allocate a counter each time <see cref="Take"/> is called. Unused counters
  26. /// passed to <see cref="Return"/> are simply left for the .NET garbage collector to deal with.
  27. /// </summary>
  28. public class GCAtomicCounterPool : IAtomicCounterPool
  29. {
  30. /// <summary>
  31. /// Return a newly-allocated atomic counterfrom the pool.
  32. /// </summary>
  33. /// <returns>an atomic counter</returns>
  34. public AtomicCounter Take()
  35. {
  36. return new AtomicCounter();
  37. }
  38. /// <summary>
  39. /// The expectation of an actual pool is that this method returns the given counter to the manager pool.
  40. /// This particular implementation does nothing.
  41. /// </summary>
  42. /// <param name="counter">a reference to the counter being returned</param>
  43. public void Return(AtomicCounter counter)
  44. { }
  45. /// <summary>
  46. /// The expectation of an actual pool is that the Dispose method will release the pools currently cached in this manager.
  47. /// This particular implementation does nothing.
  48. /// </summary>
  49. public void Dispose()
  50. {
  51. Dispose(true);
  52. GC.SuppressFinalize(this);
  53. }
  54. /// <summary>
  55. /// Release the counters currently cached in this manager (however in this case, this does nothing).
  56. /// </summary>
  57. /// <param name="disposing">true if managed resources are to be disposed</param>
  58. protected virtual void Dispose(bool disposing)
  59. {
  60. }
  61. }
  62. /// <summary>
  63. /// Contains a singleton instance of <see cref="IAtomicCounterPool"/> used for allocating atomic counters
  64. /// for <see cref="Msg"/> instances with type <see cref="MsgType.Pool"/>.
  65. /// </summary>
  66. /// <remarks>
  67. /// Sending and receiving messages with pooling mode, requires the use of atomic counters.
  68. /// You can use the AtomicCounterPool class to pool counters for reuse, reducing allocation, deallocation and garbage collection.
  69. /// <para/>
  70. /// The default implementation is <see cref="GCAtomicCounterPool"/>.
  71. /// <list type="bullet">
  72. /// <item>Call <see cref="SetGCCounterPool"/> to reinstate the default <see cref="GCBufferPool"/>.</item>
  73. /// <item>Call <see cref="SetCustomCounterPool"/> to substitute a custom implementation for the allocation and
  74. /// deallocation of atomic counters.</item>
  75. /// </list>
  76. /// </remarks>
  77. public static class AtomicCounterPool
  78. {
  79. private static IAtomicCounterPool s_counterPool = new GCAtomicCounterPool();
  80. /// <summary>
  81. /// Set BufferPool to use the <see cref="GCBufferPool"/> (which it does by default).
  82. /// </summary>
  83. public static void SetGCCounterPool()
  84. {
  85. SetCustomCounterPool(new GCAtomicCounterPool());
  86. }
  87. /// <summary>
  88. /// Set BufferPool to use the specified IAtomicCounterPool implementation to manage the pool.
  89. /// </summary>
  90. /// <param name="counterPool">the implementation of <see cref="IAtomicCounterPool"/> to use</param>
  91. public static void SetCustomCounterPool(IAtomicCounterPool counterPool)
  92. {
  93. var prior = Interlocked.Exchange(ref s_counterPool, counterPool);
  94. prior?.Dispose();
  95. }
  96. /// <summary>
  97. /// Allocate an atomic counter from the current <see cref="IAtomicCounterPool"/>.
  98. /// </summary>
  99. /// <returns>an atomic counter</returns>
  100. public static AtomicCounter Take()
  101. {
  102. return s_counterPool.Take();
  103. }
  104. /// <summary>
  105. /// Returns <paramref name="counter"/> to the <see cref="IAtomicCounterPool"/>.
  106. /// </summary>
  107. /// <param name="counter">The atomic counter to be returned to the pool.</param>
  108. public static void Return(AtomicCounter counter)
  109. {
  110. s_counterPool.Return(counter);
  111. }
  112. }
  113. }