ArrayPool.cs 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. // Licensed to the .NET Foundation under one or more agreements.
  2. // The .NET Foundation licenses this file to you under the MIT license.
  3. // See the LICENSE file in the project root for more information.
  4. #if NETCORE
  5. using System.Runtime.CompilerServices;
  6. using System.Threading;
  7. namespace SharpCompress.Buffers
  8. {
  9. /// <summary>
  10. /// Provides a resource pool that enables reusing instances of type <see cref="T:T[]"/>.
  11. /// </summary>
  12. /// <remarks>
  13. /// <para>
  14. /// Renting and returning buffers with an <see cref="ArrayPool{T}"/> can increase performance
  15. /// in situations where arrays are created and destroyed frequently, resulting in significant
  16. /// memory pressure on the garbage collector.
  17. /// </para>
  18. /// <para>
  19. /// This class is thread-safe. All members may be used by multiple threads concurrently.
  20. /// </para>
  21. /// </remarks>
  22. internal abstract class ArrayPool<T>
  23. {
  24. /// <summary>The lazily-initialized shared pool instance.</summary>
  25. private static ArrayPool<T> s_sharedInstance = null;
  26. /// <summary>
  27. /// Retrieves a shared <see cref="ArrayPool{T}"/> instance.
  28. /// </summary>
  29. /// <remarks>
  30. /// The shared pool provides a default implementation of <see cref="ArrayPool{T}"/>
  31. /// that's intended for general applicability. It maintains arrays of multiple sizes, and
  32. /// may hand back a larger array than was actually requested, but will never hand back a smaller
  33. /// array than was requested. Renting a buffer from it with <see cref="Rent"/> will result in an
  34. /// existing buffer being taken from the pool if an appropriate buffer is available or in a new
  35. /// buffer being allocated if one is not available.
  36. /// </remarks>
  37. public static ArrayPool<T> Shared
  38. {
  39. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  40. get { return Volatile.Read(ref s_sharedInstance) ?? EnsureSharedCreated(); }
  41. }
  42. /// <summary>Ensures that <see cref="s_sharedInstance"/> has been initialized to a pool and returns it.</summary>
  43. [MethodImpl(MethodImplOptions.NoInlining)]
  44. private static ArrayPool<T> EnsureSharedCreated()
  45. {
  46. Interlocked.CompareExchange(ref s_sharedInstance, Create(), null);
  47. return s_sharedInstance;
  48. }
  49. /// <summary>
  50. /// Creates a new <see cref="ArrayPool{T}"/> instance using default configuration options.
  51. /// </summary>
  52. /// <returns>A new <see cref="ArrayPool{T}"/> instance.</returns>
  53. public static ArrayPool<T> Create()
  54. {
  55. return new DefaultArrayPool<T>();
  56. }
  57. /// <summary>
  58. /// Creates a new <see cref="ArrayPool{T}"/> instance using custom configuration options.
  59. /// </summary>
  60. /// <param name="maxArrayLength">The maximum length of array instances that may be stored in the pool.</param>
  61. /// <param name="maxArraysPerBucket">
  62. /// The maximum number of array instances that may be stored in each bucket in the pool. The pool
  63. /// groups arrays of similar lengths into buckets for faster access.
  64. /// </param>
  65. /// <returns>A new <see cref="ArrayPool{T}"/> instance with the specified configuration options.</returns>
  66. /// <remarks>
  67. /// The created pool will group arrays into buckets, with no more than <paramref name="maxArraysPerBucket"/>
  68. /// in each bucket and with those arrays not exceeding <paramref name="maxArrayLength"/> in length.
  69. /// </remarks>
  70. public static ArrayPool<T> Create(int maxArrayLength, int maxArraysPerBucket)
  71. {
  72. return new DefaultArrayPool<T>(maxArrayLength, maxArraysPerBucket);
  73. }
  74. /// <summary>
  75. /// Retrieves a buffer that is at least the requested length.
  76. /// </summary>
  77. /// <param name="minimumLength">The minimum length of the array needed.</param>
  78. /// <returns>
  79. /// An <see cref="T:T[]"/> that is at least <paramref name="minimumLength"/> in length.
  80. /// </returns>
  81. /// <remarks>
  82. /// This buffer is loaned to the caller and should be returned to the same pool via
  83. /// <see cref="Return"/> so that it may be reused in subsequent usage of <see cref="Rent"/>.
  84. /// It is not a fatal error to not return a rented buffer, but failure to do so may lead to
  85. /// decreased application performance, as the pool may need to create a new buffer to replace
  86. /// the one lost.
  87. /// </remarks>
  88. public abstract T[] Rent(int minimumLength);
  89. /// <summary>
  90. /// Returns to the pool an array that was previously obtained via <see cref="Rent"/> on the same
  91. /// <see cref="ArrayPool{T}"/> instance.
  92. /// </summary>
  93. /// <param name="array">
  94. /// The buffer previously obtained from <see cref="Rent"/> to return to the pool.
  95. /// </param>
  96. /// <param name="clearArray">
  97. /// If <c>true</c> and if the pool will store the buffer to enable subsequent reuse, <see cref="Return"/>
  98. /// will clear <paramref name="array"/> of its contents so that a subsequent consumer via <see cref="Rent"/>
  99. /// will not see the previous consumer's content. If <c>false</c> or if the pool will release the buffer,
  100. /// the array's contents are left unchanged.
  101. /// </param>
  102. /// <remarks>
  103. /// Once a buffer has been returned to the pool, the caller gives up all ownership of the buffer
  104. /// and must not use it. The reference returned from a given call to <see cref="Rent"/> must only be
  105. /// returned via <see cref="Return"/> once. The default <see cref="ArrayPool{T}"/>
  106. /// may hold onto the returned buffer in order to rent it again, or it may release the returned buffer
  107. /// if it's determined that the pool already has enough buffers stored.
  108. /// </remarks>
  109. public abstract void Return(T[] array, bool clearArray = false);
  110. }
  111. }
  112. #endif