Nenhuma descrição
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

UnsafeAtomicCounter.cs 7.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. using System.Threading;
  2. using Unity.Mathematics;
  3. namespace Unity.Collections.LowLevel.Unsafe
  4. {
  5. /// <summary>
  6. /// A 32-bit atomic counter.
  7. /// </summary>
  8. /// <remarks>Rather than have its own int, a counter *points* to an int. This arrangement lets counters in different jobs share reference to the same underlying int.</remarks>
  9. [GenerateTestsForBurstCompatibility]
  10. public unsafe struct UnsafeAtomicCounter32
  11. {
  12. /// <summary>
  13. /// The int that is modified by this counter.
  14. /// </summary>
  15. /// <value>The int that is modified by this counter.</value>
  16. public int* Counter;
  17. /// <summary>
  18. /// Initializes and returns an instance of UnsafeAtomicCounter32.
  19. /// </summary>
  20. /// <param name="ptr">A pointer to the int to be modified by this counter.</param>
  21. public UnsafeAtomicCounter32(void* ptr)
  22. {
  23. Counter = (int*)ptr;
  24. }
  25. /// <summary>
  26. /// Non-atomically sets this counter to a value.
  27. /// </summary>
  28. /// <param name="value">The value to set. Defaults to 0</param>
  29. public void Reset(int value = 0)
  30. {
  31. *Counter = value;
  32. }
  33. /// <summary>
  34. /// Atomically adds a value to this counter.
  35. /// </summary>
  36. /// <param name="value">The value to add.</param>
  37. /// <returns>The original value before the add.</returns>
  38. public int Add(int value)
  39. {
  40. return Interlocked.Add(ref UnsafeUtility.AsRef<int>(Counter), value) - value;
  41. }
  42. /// <summary>
  43. /// Atomically subtracts a value from this counter.
  44. /// </summary>
  45. /// <param name="value">The value to subtract.</param>
  46. /// <returns>The original value before the subtract.</returns>
  47. public int Sub(int value) => Add(-value);
  48. /// <summary>
  49. /// Atomically adds a value to this counter. The result will not be greater than a maximum value.
  50. /// </summary>
  51. /// <param name="value">The value to add to this counter.</param>
  52. /// <param name="max">The maximum which the result will not be greater than.</param>
  53. /// <returns>The original value before the add.</returns>
  54. public int AddSat(int value, int max = int.MaxValue)
  55. {
  56. int oldVal;
  57. int newVal = *Counter;
  58. do
  59. {
  60. oldVal = newVal;
  61. newVal = newVal >= max ? max : math.min(max, newVal + value);
  62. newVal = Interlocked.CompareExchange(ref UnsafeUtility.AsRef<int>(Counter), newVal, oldVal);
  63. }
  64. while (oldVal != newVal && oldVal != max);
  65. return oldVal;
  66. }
  67. /// <summary>
  68. /// Atomically subtracts a value from this counter. The result will not be less than a minimum value.
  69. /// </summary>
  70. /// <param name="value">The value to subtract from this counter.</param>
  71. /// <param name="min">The minimum which the result will not be less than.</param>
  72. /// <returns>The original value before the subtract.</returns>
  73. public int SubSat(int value, int min = int.MinValue)
  74. {
  75. int oldVal;
  76. int newVal = *Counter;
  77. do
  78. {
  79. oldVal = newVal;
  80. newVal = newVal <= min ? min : math.max(min, newVal - value);
  81. newVal = Interlocked.CompareExchange(ref UnsafeUtility.AsRef<int>(Counter), newVal, oldVal);
  82. }
  83. while (oldVal != newVal && oldVal != min);
  84. return oldVal;
  85. }
  86. }
  87. /// <summary>
  88. /// A 64-bit atomic counter.
  89. /// </summary>
  90. /// <remarks>Rather than have its own long, a counter *points* to a long. This arrangement lets counters in different jobs share reference to the same underlying long.</remarks>
  91. [GenerateTestsForBurstCompatibility]
  92. public unsafe struct UnsafeAtomicCounter64
  93. {
  94. /// <summary>
  95. /// The long that is modified by this counter.
  96. /// </summary>
  97. /// <value>The long that is modified by this counter.</value>
  98. public long* Counter;
  99. /// <summary>
  100. /// Initializes and returns an instance of UnsafeAtomicCounter64.
  101. /// </summary>
  102. /// <param name="ptr">A pointer to the long to be modified by this counter.</param>
  103. public UnsafeAtomicCounter64(void* ptr)
  104. {
  105. Counter = (long*)ptr;
  106. }
  107. /// <summary>
  108. /// Non-atomically sets this counter to a value.
  109. /// </summary>
  110. /// <param name="value">The value to set. Defaults to 0</param>
  111. public void Reset(long value = 0)
  112. {
  113. *Counter = value;
  114. }
  115. /// <summary>
  116. /// Atomically adds a value to this counter.
  117. /// </summary>
  118. /// <param name="value">The value to add.</param>
  119. /// <returns>The original value before the add.</returns>
  120. public long Add(long value)
  121. {
  122. return Interlocked.Add(ref UnsafeUtility.AsRef<long>(Counter), value) - value;
  123. }
  124. /// <summary>
  125. /// Atomically subtracts a value from this counter.
  126. /// </summary>
  127. /// <param name="value">The value to subtract.</param>
  128. /// <returns>The original value before the subtract.</returns>
  129. public long Sub(long value) => Add(-value);
  130. /// <summary>
  131. /// Atomically adds a value to this counter. The result will not be greater than a maximum value.
  132. /// </summary>
  133. /// <param name="value">The value to add to this counter.</param>
  134. /// <param name="max">The maximum which the result will not be greater than.</param>
  135. /// <returns>The original value before the add.</returns>
  136. public long AddSat(long value, long max = long.MaxValue)
  137. {
  138. long oldVal;
  139. long newVal = *Counter;
  140. do
  141. {
  142. oldVal = newVal;
  143. newVal = newVal >= max ? max : math.min(max, newVal + value);
  144. newVal = Interlocked.CompareExchange(ref UnsafeUtility.AsRef<long>(Counter), newVal, oldVal);
  145. }
  146. while (oldVal != newVal && oldVal != max);
  147. return oldVal;
  148. }
  149. /// <summary>
  150. /// Atomically subtracts a value from this counter. The result will not be less than a minimum value.
  151. /// </summary>
  152. /// <param name="value">The value to subtract from this counter.</param>
  153. /// <param name="min">The minimum which the result will not be less than.</param>
  154. /// <returns>The original value before the subtract.</returns>
  155. public long SubSat(long value, long min = long.MinValue)
  156. {
  157. long oldVal;
  158. long newVal = *Counter;
  159. do
  160. {
  161. oldVal = newVal;
  162. newVal = newVal <= min ? min : math.max(min, newVal - value);
  163. newVal = Interlocked.CompareExchange(ref UnsafeUtility.AsRef<long>(Counter), newVal, oldVal);
  164. }
  165. while (oldVal != newVal && oldVal != min);
  166. return oldVal;
  167. }
  168. }
  169. }