Без опису
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. using System;
  2. using System.Threading;
  3. using Unity.Collections.LowLevel.Unsafe;
  4. using Unity.Mathematics;
  5. #pragma warning disable 0649
  6. namespace Unity.Collections
  7. {
  8. internal struct Long8
  9. {
  10. internal long f0,f1,f2,f3,f4,f5,f6,f7;
  11. }
  12. internal struct Long64
  13. {
  14. internal Long8 f0,f1,f2,f3,f4,f5,f6,f7;
  15. }
  16. internal struct Long512
  17. {
  18. internal Long64 f0,f1,f2,f3,f4,f5,f6,f7;
  19. }
  20. internal struct Long1024 : IIndexable<long>
  21. {
  22. internal Long512 f0,f1;
  23. public int Length { get { return 1024;} set {} }
  24. public ref long ElementAt(int index)
  25. {
  26. unsafe { fixed(Long512* p = &f0) {
  27. return ref UnsafeUtility.AsRef<long>((long*)p + index);
  28. } }
  29. }
  30. }
  31. internal class ConcurrentMask
  32. {
  33. internal static long AtomicOr(ref long destination, long source)
  34. {
  35. var readValue = Interlocked.Read(ref destination);
  36. long oldReadValue, writtenValue;
  37. do
  38. {
  39. writtenValue = readValue | source;
  40. oldReadValue = readValue;
  41. readValue = Interlocked.CompareExchange(ref destination, writtenValue, oldReadValue);
  42. } while(readValue != oldReadValue);
  43. return writtenValue;
  44. }
  45. internal static long AtomicAnd(ref long destination, long source)
  46. {
  47. var readValue = Interlocked.Read(ref destination);
  48. long oldReadValue, writtenValue;
  49. do
  50. {
  51. writtenValue = readValue & source;
  52. oldReadValue = readValue;
  53. readValue = Interlocked.CompareExchange(ref destination, writtenValue, oldReadValue);
  54. } while(readValue != oldReadValue);
  55. return writtenValue;
  56. }
  57. internal static void longestConsecutiveOnes(long value, out int offset, out int count)
  58. {
  59. count = 0;
  60. var newvalue = value;
  61. while(newvalue != 0)
  62. {
  63. value = newvalue;
  64. newvalue = value & (long)((ulong)value >> 1);
  65. ++count;
  66. }
  67. offset = math.tzcnt(value);
  68. }
  69. internal static bool foundAtLeastThisManyConsecutiveOnes(long value, int minimum, out int offset, out int count)
  70. {
  71. if(minimum == 1)
  72. {
  73. offset = math.tzcnt(value); // find offset of first 1 bit
  74. count = 1;
  75. return offset != 64;
  76. }
  77. longestConsecutiveOnes(value, out offset, out count);
  78. return count >= minimum;
  79. }
  80. internal static bool foundAtLeastThisManyConsecutiveZeroes(long value, int minimum, out int offset, out int count)
  81. {
  82. return foundAtLeastThisManyConsecutiveOnes(~value, minimum, out offset, out count);
  83. }
  84. internal const int ErrorFailedToFree = -1;
  85. internal const int ErrorFailedToAllocate = -2;
  86. internal const int ErrorAllocationCrossesWordBoundary = -3;
  87. internal const int EmptyBeforeAllocation = 0;
  88. internal const int EmptyAfterFree = 0;
  89. internal static bool Succeeded(int error)
  90. {
  91. return error >= 0;
  92. }
  93. internal static long MakeMask(int offset, int bits)
  94. {
  95. return (long)(~0UL >> (64-bits)) << offset;
  96. }
  97. internal static int TryAllocate(ref long l, int offset, int bits)
  98. {
  99. var mask = MakeMask(offset, bits);
  100. var readValue = Interlocked.Read(ref l);
  101. long oldReadValue, writtenValue;
  102. do
  103. {
  104. if((readValue & mask) != 0)
  105. return ErrorFailedToAllocate;
  106. writtenValue = readValue | mask;
  107. oldReadValue = readValue;
  108. readValue = Interlocked.CompareExchange(ref l, writtenValue, oldReadValue);
  109. } while(readValue != oldReadValue);
  110. return math.countbits(readValue); // how many bits were set, before i allocated? sometimes if 0, do something special (allocate chunk?)
  111. }
  112. internal static int TryFree(ref long l, int offset, int bits)
  113. {
  114. var mask = MakeMask(offset, bits);
  115. var readValue = Interlocked.Read(ref l);
  116. long oldReadValue, writtenValue;
  117. do
  118. {
  119. if((readValue & mask) != mask)
  120. return ErrorFailedToFree;
  121. writtenValue = readValue & ~mask;
  122. oldReadValue = readValue;
  123. readValue = Interlocked.CompareExchange(ref l, writtenValue, oldReadValue);
  124. } while(readValue != oldReadValue);
  125. return math.countbits(writtenValue); // how many bits are set, after i freed? sometimes if 0, do something special (free chunk?)
  126. }
  127. internal static int TryAllocate(ref long l, out int offset, int bits)
  128. {
  129. var readValue = Interlocked.Read(ref l);
  130. long oldReadValue, writtenValue;
  131. do
  132. {
  133. if(!foundAtLeastThisManyConsecutiveZeroes(readValue, bits, out offset, out int _))
  134. return ErrorFailedToAllocate;
  135. var mask = MakeMask(offset, bits);
  136. writtenValue = readValue | mask;
  137. oldReadValue = readValue;
  138. readValue = Interlocked.CompareExchange(ref l, writtenValue, oldReadValue);
  139. } while(readValue != oldReadValue);
  140. return math.countbits(readValue); // how many bits were set, before i allocated? sometimes if 0, do something special (allocate chunk?)
  141. }
  142. internal static int TryAllocate<T>(ref T t, int offset, int bits) where T : IIndexable<long>
  143. {
  144. var wordOffset = offset >> 6;
  145. var bitOffset = offset & 63;
  146. if(bitOffset + bits > 64)
  147. return ErrorAllocationCrossesWordBoundary;
  148. return TryAllocate(ref t.ElementAt(wordOffset), bitOffset, bits);
  149. }
  150. internal static int TryFree<T>(ref T t, int offset, int bits) where T : IIndexable<long>
  151. {
  152. var wordOffset = offset >> 6;
  153. var bitOffset = offset & 63;
  154. return TryFree(ref t.ElementAt(wordOffset), bitOffset, bits);
  155. }
  156. internal static int TryAllocate<T>(ref T t, out int offset, int begin, int end, int bits) where T : IIndexable<long>
  157. {
  158. var wordOffset = begin;
  159. for(; wordOffset < end; ++wordOffset)
  160. if(t.ElementAt(wordOffset) != ~0L)
  161. break;
  162. for(; wordOffset < end; ++wordOffset)
  163. {
  164. int error, bitOffset;
  165. error = TryAllocate(ref t.ElementAt(wordOffset), out bitOffset, bits);
  166. if(Succeeded(error))
  167. {
  168. offset = wordOffset * 64 + bitOffset;
  169. return error;
  170. }
  171. }
  172. offset = -1;
  173. return ErrorFailedToAllocate;
  174. }
  175. internal static int TryAllocate<T>(ref T t, out int offset, int begin, int bits) where T : IIndexable<long>
  176. {
  177. var error = TryAllocate(ref t, out offset, begin, t.Length, bits);
  178. if(Succeeded(error))
  179. return error;
  180. return TryAllocate(ref t, out offset, 0, begin, bits);
  181. }
  182. internal static int TryAllocate<T>(ref T t, out int offset, int bits) where T : IIndexable<long>
  183. {
  184. return TryAllocate(ref t, out offset, 0, t.Length, bits);
  185. }
  186. }
  187. }