ExNativeMultiHashMap.cs 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. // Magica Cloth.
  2. // Copyright (c) MagicaSoft, 2020-2022.
  3. // https://magicasoft.jp
  4. using System;
  5. using System.Collections.Generic;
  6. using Unity.Collections;
  7. namespace MagicaCloth
  8. {
  9. /// <summary>
  10. /// NativeMultiHashMapの機能拡張版
  11. /// </summary>
  12. /// <typeparam name="TKey"></typeparam>
  13. /// <typeparam name="TValue"></typeparam>
  14. public class ExNativeMultiHashMap<TKey, TValue>
  15. where TKey : struct, IEquatable<TKey>
  16. where TValue : struct
  17. {
  18. /// <summary>
  19. /// ネイティブハッシュマップ
  20. /// </summary>
  21. NativeMultiHashMap<TKey, TValue> nativeMultiHashMap;
  22. /// <summary>
  23. /// ネイティブリストの配列数
  24. /// ※ジョブでエラーが出ないように事前に確保しておく
  25. /// </summary>
  26. int nativeLength;
  27. /// <summary>
  28. /// 使用キーの記録
  29. /// </summary>
  30. Dictionary<TKey, int> useKeyDict = new Dictionary<TKey, int>();
  31. //=========================================================================================
  32. public ExNativeMultiHashMap()
  33. {
  34. nativeMultiHashMap = new NativeMultiHashMap<TKey, TValue>(1, Allocator.Persistent);
  35. nativeLength = NativeCount;
  36. }
  37. public void Dispose()
  38. {
  39. if (nativeMultiHashMap.IsCreated)
  40. {
  41. nativeMultiHashMap.Dispose();
  42. }
  43. nativeLength = 0;
  44. }
  45. private int NativeCount
  46. {
  47. get
  48. {
  49. return nativeMultiHashMap.Count();
  50. }
  51. }
  52. //=========================================================================================
  53. public bool IsCreated
  54. {
  55. get
  56. {
  57. return nativeMultiHashMap.IsCreated;
  58. }
  59. }
  60. /// <summary>
  61. /// データ追加
  62. /// </summary>
  63. /// <param name="key"></param>
  64. /// <param name="value"></param>
  65. public void Add(TKey key, TValue value)
  66. {
  67. nativeMultiHashMap.Add(key, value);
  68. if (useKeyDict.ContainsKey(key))
  69. useKeyDict[key] = useKeyDict[key] + 1;
  70. else
  71. useKeyDict[key] = 1;
  72. nativeLength = NativeCount;
  73. }
  74. /// <summary>
  75. /// データ削除
  76. /// データ削除にはコストがかかるので注意!
  77. /// そして何故かこの関数は削除するごとに重くなる性質があるらしい(何故?)
  78. /// </summary>
  79. /// <param name="key"></param>
  80. /// <param name="value"></param>
  81. public void Remove(TKey key, TValue value)
  82. {
  83. TValue data;
  84. NativeMultiHashMapIterator<TKey> iterator;
  85. if (nativeMultiHashMap.TryGetFirstValue(key, out data, out iterator))
  86. {
  87. do
  88. {
  89. if (data.Equals(value))
  90. {
  91. // 削除
  92. nativeMultiHashMap.Remove(iterator);
  93. var cnt = useKeyDict[key] - 1;
  94. if (cnt == 0)
  95. useKeyDict.Remove(key);
  96. break;
  97. }
  98. }
  99. while (nativeMultiHashMap.TryGetNextValue(out data, ref iterator));
  100. }
  101. nativeLength = NativeCount;
  102. }
  103. /// <summary>
  104. /// 条件判定削除
  105. /// 何故か削除はこちらで一括でやったほうが早い!
  106. /// </summary>
  107. /// <param name="func">trueを返せば削除</param>
  108. public void Remove(Func<TKey, TValue, bool> func)
  109. {
  110. List<TKey> removeKey = new List<TKey>();
  111. foreach (TKey key in useKeyDict.Keys)
  112. {
  113. TValue data;
  114. NativeMultiHashMapIterator<TKey> iterator;
  115. if (nativeMultiHashMap.TryGetFirstValue(key, out data, out iterator))
  116. {
  117. do
  118. {
  119. // 削除判定
  120. if (func(key, data))
  121. {
  122. // 削除
  123. nativeMultiHashMap.Remove(iterator);
  124. var cnt = useKeyDict[key] - 1;
  125. if (cnt == 0)
  126. removeKey.Add(key);
  127. }
  128. }
  129. while (nativeMultiHashMap.TryGetNextValue(out data, ref iterator));
  130. }
  131. }
  132. foreach (var key in removeKey)
  133. useKeyDict.Remove(key);
  134. nativeLength = NativeCount;
  135. }
  136. /// <summary>
  137. /// データ置き換え
  138. /// </summary>
  139. /// <param name="func">trueを返せば置換</param>
  140. /// <param name="rdata">引数にデータを受け取り、修正したデータを返し置換する</param>
  141. public void Replace(Func<TKey, TValue, bool> func, Func<TValue, TValue> datafunc)
  142. {
  143. foreach (var key in useKeyDict.Keys)
  144. {
  145. TValue data;
  146. NativeMultiHashMapIterator<TKey> iterator;
  147. if (nativeMultiHashMap.TryGetFirstValue(key, out data, out iterator))
  148. {
  149. do
  150. {
  151. // 置換判定
  152. if (func(key, data))
  153. {
  154. // 置き換え
  155. nativeMultiHashMap.SetValue(datafunc(data), iterator);
  156. return;
  157. }
  158. }
  159. while (nativeMultiHashMap.TryGetNextValue(out data, ref iterator));
  160. }
  161. }
  162. nativeLength = NativeCount;
  163. }
  164. /// <summary>
  165. /// データに対してアクションを実行
  166. /// </summary>
  167. /// <param name="act"></param>
  168. public void Process(Action<TKey, TValue> act)
  169. {
  170. foreach (var key in useKeyDict.Keys)
  171. {
  172. TValue data;
  173. NativeMultiHashMapIterator<TKey> iterator;
  174. if (nativeMultiHashMap.TryGetFirstValue(key, out data, out iterator))
  175. {
  176. do
  177. {
  178. act(key, data);
  179. }
  180. while (nativeMultiHashMap.TryGetNextValue(out data, ref iterator));
  181. }
  182. }
  183. }
  184. /// <summary>
  185. /// キーのデータに対してアクションを実行
  186. /// </summary>
  187. /// <param name="key"></param>
  188. /// <param name="act"></param>
  189. public void Process(TKey key, Action<TValue> act)
  190. {
  191. TValue data;
  192. NativeMultiHashMapIterator<TKey> iterator;
  193. if (nativeMultiHashMap.TryGetFirstValue(key, out data, out iterator))
  194. {
  195. do
  196. {
  197. act(data);
  198. }
  199. while (nativeMultiHashMap.TryGetNextValue(out data, ref iterator));
  200. }
  201. }
  202. /// <summary>
  203. /// データが存在するか判定する
  204. /// </summary>
  205. /// <param name="key"></param>
  206. /// <param name="value"></param>
  207. /// <returns></returns>
  208. public bool Contains(TKey key, TValue value)
  209. {
  210. TValue data;
  211. NativeMultiHashMapIterator<TKey> iterator;
  212. if (nativeMultiHashMap.TryGetFirstValue(key, out data, out iterator))
  213. {
  214. do
  215. {
  216. if (data.Equals(value))
  217. {
  218. return true;
  219. }
  220. }
  221. while (nativeMultiHashMap.TryGetNextValue(out data, ref iterator));
  222. }
  223. return false;
  224. }
  225. /// <summary>
  226. /// キーが存在するか判定する
  227. /// </summary>
  228. /// <param name="key"></param>
  229. /// <returns></returns>
  230. public bool Contains(TKey key)
  231. {
  232. return useKeyDict.ContainsKey(key);
  233. }
  234. /// <summary>
  235. /// キーの削除
  236. /// </summary>
  237. /// <param name="key"></param>
  238. public void Remove(TKey key)
  239. {
  240. nativeMultiHashMap.Remove(key);
  241. useKeyDict.Remove(key);
  242. nativeLength = NativeCount;
  243. }
  244. /// <summary>
  245. /// 実際に利用されている要素数を返す
  246. /// </summary>
  247. public int Count
  248. {
  249. get
  250. {
  251. //return nativeMultiHashMap.Length;
  252. return nativeLength;
  253. }
  254. }
  255. /// <summary>
  256. /// データ削除
  257. /// </summary>
  258. public void Clear()
  259. {
  260. nativeMultiHashMap.Clear();
  261. nativeLength = 0;
  262. useKeyDict.Clear();
  263. }
  264. /// <summary>
  265. /// 内部のNativeMultiHashMapを取得する
  266. /// </summary>
  267. /// <returns></returns>
  268. public NativeMultiHashMap<TKey, TValue> Map
  269. {
  270. get
  271. {
  272. return nativeMultiHashMap;
  273. }
  274. }
  275. }
  276. }