Mirror of Svelto.ECS because we're a fan of it
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

829 lines
19KB

  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Threading;
  5. namespace Svelto.DataStructures
  6. {
  7. public struct FasterListEnumerator<T> : IEnumerator<T>
  8. {
  9. public T Current
  10. {
  11. get { return _current; }
  12. }
  13. public FasterListEnumerator(T[] buffer, int size)
  14. {
  15. _size = size;
  16. _counter = 0;
  17. _buffer = buffer;
  18. _current = default(T);
  19. }
  20. object IEnumerator.Current
  21. {
  22. get { return _current; }
  23. }
  24. T IEnumerator<T>.Current
  25. {
  26. get { return _current; }
  27. }
  28. public void Dispose()
  29. {
  30. _buffer = null;
  31. }
  32. public bool MoveNext()
  33. {
  34. if (_counter < _size)
  35. {
  36. _current = _buffer[_counter++];
  37. return true;
  38. }
  39. _current = default(T);
  40. return false;
  41. }
  42. public void Reset()
  43. {
  44. _counter = 0;
  45. }
  46. bool IEnumerator.MoveNext()
  47. {
  48. return MoveNext();
  49. }
  50. void IEnumerator.Reset()
  51. {
  52. Reset();
  53. }
  54. T[] _buffer;
  55. int _counter;
  56. int _size;
  57. T _current;
  58. }
  59. public struct FasterListEnumeratorCast<T, U> : IEnumerator<T> where T:U
  60. {
  61. public T Current
  62. {
  63. get { return (T)_buffer.Current; }
  64. }
  65. public FasterListEnumeratorCast(FasterListEnumerator<U> buffer)
  66. {
  67. _buffer = buffer;
  68. }
  69. object IEnumerator.Current
  70. {
  71. get { return (T)_buffer.Current; }
  72. }
  73. T IEnumerator<T>.Current
  74. {
  75. get { return (T)_buffer.Current; }
  76. }
  77. public void Dispose()
  78. {}
  79. public bool MoveNext()
  80. {
  81. return _buffer.MoveNext();
  82. }
  83. public void Reset()
  84. {
  85. _buffer.Reset();
  86. }
  87. bool IEnumerator.MoveNext()
  88. {
  89. return MoveNext();
  90. }
  91. void IEnumerator.Reset()
  92. {
  93. Reset();
  94. }
  95. FasterListEnumerator<U> _buffer;
  96. }
  97. public struct FasterReadOnlyList<T> : IList<T>
  98. {
  99. public static FasterReadOnlyList<T> DefaultList = new FasterReadOnlyList<T>(FasterList<T>.DefaultList);
  100. public int Count { get { return _list.Count; } }
  101. public bool IsReadOnly { get { return true; } }
  102. public FasterReadOnlyList(FasterList<T> list)
  103. {
  104. _list = list;
  105. int count;
  106. _buffer = FasterList<T>.NoVirt.ToArrayFast(list, out count);
  107. }
  108. public T this[int index] { get { return _buffer[index]; } set { throw new NotImplementedException(); } }
  109. public FasterListEnumerator<T> GetEnumerator()
  110. {
  111. return _list.GetEnumerator();
  112. }
  113. public void Add(T item)
  114. {
  115. throw new NotImplementedException();
  116. }
  117. public void Clear()
  118. {
  119. throw new NotImplementedException();
  120. }
  121. public bool Contains(T item)
  122. {
  123. return _list.Contains(item);
  124. }
  125. public void CopyTo(T[] array, int arrayIndex)
  126. {
  127. _list.CopyTo(array, arrayIndex);
  128. }
  129. public bool Remove(T item)
  130. {
  131. throw new NotImplementedException();
  132. }
  133. public int IndexOf(T item)
  134. {
  135. return _list.IndexOf(item);
  136. }
  137. public void Insert(int index, T item)
  138. {
  139. throw new NotImplementedException();
  140. }
  141. public void RemoveAt(int index)
  142. {
  143. throw new NotImplementedException();
  144. }
  145. IEnumerator<T> IEnumerable<T>.GetEnumerator()
  146. {
  147. return GetEnumerator();
  148. }
  149. IEnumerator IEnumerable.GetEnumerator()
  150. {
  151. return GetEnumerator();
  152. }
  153. readonly FasterList<T> _list;
  154. private readonly T[] _buffer;
  155. }
  156. public struct FasterListThreadSafe<T> : IList<T>
  157. {
  158. public FasterListThreadSafe(FasterList<T> list)
  159. {
  160. if (list == null) throw new ArgumentException("invalid list");
  161. _list = list;
  162. _lockQ = new ReaderWriterLockSlim();
  163. }
  164. public int Count
  165. {
  166. get
  167. {
  168. _lockQ.EnterReadLock();
  169. try
  170. {
  171. return _list.Count;
  172. }
  173. finally
  174. {
  175. _lockQ.ExitReadLock();
  176. }
  177. }
  178. }
  179. public bool IsReadOnly { get { return false; } }
  180. public T this[int index]
  181. {
  182. get
  183. {
  184. _lockQ.EnterReadLock();
  185. try
  186. {
  187. return _list[index];
  188. }
  189. finally
  190. {
  191. _lockQ.ExitReadLock();
  192. }
  193. }
  194. set
  195. {
  196. _lockQ.EnterWriteLock();
  197. try
  198. {
  199. _list[index] = value;
  200. }
  201. finally
  202. {
  203. _lockQ.ExitWriteLock();
  204. }
  205. }
  206. }
  207. public FasterListEnumerator<T> GetEnumerator()
  208. {
  209. throw new NotImplementedException();
  210. }
  211. public void Add(T item)
  212. {
  213. _lockQ.EnterWriteLock();
  214. try
  215. {
  216. _list.Add(item);
  217. }
  218. finally
  219. {
  220. _lockQ.ExitWriteLock();
  221. }
  222. }
  223. public void Clear()
  224. {
  225. _lockQ.EnterWriteLock();
  226. try
  227. {
  228. _list.Clear();
  229. }
  230. finally
  231. {
  232. _lockQ.ExitWriteLock();
  233. }
  234. }
  235. public void FastClear()
  236. {
  237. _lockQ.EnterWriteLock();
  238. try
  239. {
  240. _list.FastClear();
  241. }
  242. finally
  243. {
  244. _lockQ.ExitWriteLock();
  245. }
  246. }
  247. public bool Contains(T item)
  248. {
  249. _lockQ.EnterReadLock();
  250. try
  251. {
  252. return _list.Contains(item);
  253. }
  254. finally
  255. {
  256. _lockQ.ExitReadLock();
  257. }
  258. }
  259. public void CopyTo(T[] array, int arrayIndex)
  260. {
  261. _lockQ.EnterReadLock();
  262. try
  263. {
  264. _list.CopyTo(array, arrayIndex);
  265. }
  266. finally
  267. {
  268. _lockQ.ExitReadLock();
  269. }
  270. }
  271. public bool Remove(T item)
  272. {
  273. _lockQ.EnterWriteLock();
  274. try
  275. {
  276. return _list.Remove(item);
  277. }
  278. finally
  279. {
  280. _lockQ.ExitWriteLock();
  281. }
  282. }
  283. public int IndexOf(T item)
  284. {
  285. _lockQ.EnterReadLock();
  286. try
  287. {
  288. return _list.IndexOf(item);
  289. }
  290. finally
  291. {
  292. _lockQ.ExitReadLock();
  293. }
  294. }
  295. public void Insert(int index, T item)
  296. {
  297. _lockQ.EnterWriteLock();
  298. try
  299. {
  300. _list.Insert(index, item);
  301. }
  302. finally
  303. {
  304. _lockQ.ExitWriteLock();
  305. }
  306. }
  307. public void RemoveAt(int index)
  308. {
  309. _lockQ.EnterWriteLock();
  310. try
  311. {
  312. _list.RemoveAt(index);
  313. }
  314. finally
  315. {
  316. _lockQ.ExitWriteLock();
  317. }
  318. }
  319. public void UnorderedRemoveAt(int index)
  320. {
  321. _lockQ.EnterWriteLock();
  322. try
  323. {
  324. _list.UnorderedRemoveAt(index);
  325. }
  326. finally
  327. {
  328. _lockQ.ExitWriteLock();
  329. }
  330. }
  331. IEnumerator<T> IEnumerable<T>.GetEnumerator()
  332. {
  333. throw new NotImplementedException();
  334. }
  335. IEnumerator IEnumerable.GetEnumerator()
  336. {
  337. throw new NotImplementedException();
  338. }
  339. readonly FasterList<T> _list;
  340. readonly ReaderWriterLockSlim _lockQ;
  341. }
  342. public struct FasterReadOnlyListCast<T, U> : IList<U> where U:T
  343. {
  344. public static readonly FasterReadOnlyListCast<T, U> DefaultList = new FasterReadOnlyListCast<T, U>(new FasterList<T>());
  345. public int Count { get { return _list.Count; } }
  346. public bool IsReadOnly { get { return true; } }
  347. public FasterReadOnlyListCast(FasterList<T> list)
  348. {
  349. _list = list;
  350. }
  351. public U this[int index] { get { return (U)_list[index]; } set { throw new NotImplementedException(); } }
  352. public FasterListEnumeratorCast<U, T> GetEnumerator()
  353. {
  354. return new FasterListEnumeratorCast<U, T>(_list.GetEnumerator());
  355. }
  356. public void Add(U item)
  357. {
  358. throw new NotImplementedException();
  359. }
  360. public void Clear()
  361. {
  362. throw new NotImplementedException();
  363. }
  364. public bool Contains(U item)
  365. {
  366. return _list.Contains(item);
  367. }
  368. public void CopyTo(U[] array, int arrayIndex)
  369. {
  370. Array.Copy(_list.ToArrayFast(), 0, array, arrayIndex, _list.Count);
  371. }
  372. public bool Remove(U item)
  373. {
  374. throw new NotImplementedException();
  375. }
  376. public int IndexOf(U item)
  377. {
  378. return _list.IndexOf(item);
  379. }
  380. public void Insert(int index, U item)
  381. {
  382. throw new NotImplementedException();
  383. }
  384. public void RemoveAt(int index)
  385. {
  386. throw new NotImplementedException();
  387. }
  388. IEnumerator<U> IEnumerable<U>.GetEnumerator()
  389. {
  390. return GetEnumerator();
  391. }
  392. IEnumerator IEnumerable.GetEnumerator()
  393. {
  394. return GetEnumerator();
  395. }
  396. readonly FasterList<T> _list;
  397. }
  398. public interface IFasterList
  399. {}
  400. public class FasterList<T> : IList<T>, IFasterList
  401. {
  402. public static readonly FasterList<T> DefaultList = new FasterList<T>();
  403. const int MIN_SIZE = 4;
  404. public int Count
  405. {
  406. get { return _count; }
  407. }
  408. public bool IsReadOnly
  409. {
  410. get { return false; }
  411. }
  412. public FasterList()
  413. {
  414. _count = 0;
  415. _buffer = new T[MIN_SIZE];
  416. }
  417. public FasterList(int initialSize)
  418. {
  419. _count = 0;
  420. _buffer = new T[initialSize];
  421. }
  422. public FasterList(ICollection<T> collection)
  423. {
  424. _buffer = new T[collection.Count];
  425. collection.CopyTo(_buffer, 0);
  426. _count = _buffer.Length;
  427. }
  428. public FasterList(FasterList<T> listCopy)
  429. {
  430. _buffer = new T[listCopy.Count];
  431. listCopy.CopyTo(_buffer, 0);
  432. _count = listCopy.Count;
  433. }
  434. public T this[int i]
  435. {
  436. get { DesignByContract.Check.Require(i < _count, "out of bound index"); return _buffer[i]; }
  437. set { DesignByContract.Check.Require(i < _count, "out of bound index"); _buffer[i] = value; }
  438. }
  439. public void Add(T item)
  440. {
  441. if (_count == _buffer.Length)
  442. AllocateMore();
  443. _buffer[_count++] = item;
  444. }
  445. /// <summary>
  446. /// this is a dirtish trick to be able to use the index operastor
  447. /// before adding the elements through the Add functions
  448. /// </summary>
  449. /// <typeparam name="U"></typeparam>
  450. /// <param name="initialSize"></param>
  451. /// <returns></returns>
  452. public static FasterList<T> PreFill<U>(int initialSize) where U:T, new()
  453. {
  454. var list = new FasterList<T>(initialSize);
  455. for (int i = 0; i < initialSize; i++)
  456. list.Add(new U());
  457. list._count = 0;
  458. return list;
  459. }
  460. public void AddRange(IEnumerable<T> items, int count)
  461. {
  462. AddRange(items.GetEnumerator(), count);
  463. }
  464. public void AddRange(IEnumerator<T> items, int count)
  465. {
  466. if (_count + count >= _buffer.Length)
  467. AllocateMore(_count + count);
  468. while (items.MoveNext())
  469. _buffer[_count++] = items.Current;
  470. }
  471. public void AddRange(ICollection<T> items)
  472. {
  473. AddRange(items.GetEnumerator(), items.Count);
  474. }
  475. public void AddRange(FasterList<T> items)
  476. {
  477. AddRange(items.ToArrayFast(), items.Count);
  478. }
  479. public void AddRange(T[] items, int count)
  480. {
  481. if (count == 0) return;
  482. if (_count + count >= _buffer.Length)
  483. AllocateMore(_count + count);
  484. Array.Copy(items, 0, _buffer, _count, count);
  485. _count += count;
  486. }
  487. public void AddRange(T[] items)
  488. {
  489. AddRange(items, items.Length);
  490. }
  491. public FasterReadOnlyList<T> AsReadOnly()
  492. {
  493. return new FasterReadOnlyList<T>(this);
  494. }
  495. /// <summary>
  496. /// Careful, you could keep on holding references you don't want to hold to anymore
  497. /// Use DeepClear in case.
  498. /// </summary>
  499. public void FastClear()
  500. {
  501. _count = 0;
  502. }
  503. public void Clear()
  504. {
  505. Array.Clear(_buffer, 0, _buffer.Length);
  506. _count = 0;
  507. }
  508. public bool Contains(T item)
  509. {
  510. var index = IndexOf(item);
  511. return index != -1;
  512. }
  513. public void CopyTo(T[] array, int arrayIndex)
  514. {
  515. Array.Copy(_buffer, 0, array, arrayIndex, Count);
  516. }
  517. public FasterListEnumerator<T> GetEnumerator()
  518. {
  519. return new FasterListEnumerator<T>(_buffer, Count);
  520. }
  521. public int IndexOf(T item)
  522. {
  523. var comp = EqualityComparer<T>.Default;
  524. for (var index = 0; index < _count; index++)
  525. if (comp.Equals(_buffer[index], item))
  526. return index;
  527. return -1;
  528. }
  529. public void Insert(int index, T item)
  530. {
  531. DesignByContract.Check.Require(index < _count, "out of bound index");
  532. if (_count == _buffer.Length) AllocateMore();
  533. Array.Copy(_buffer, index, _buffer, index + 1, _count - index);
  534. _buffer[index] = item;
  535. ++_count;
  536. }
  537. public void Release()
  538. {
  539. _count = 0;
  540. _buffer = null;
  541. }
  542. public bool Remove(T item)
  543. {
  544. var index = IndexOf(item);
  545. if (index == -1)
  546. return false;
  547. RemoveAt(index);
  548. return true;
  549. }
  550. public void RemoveAt(int index)
  551. {
  552. DesignByContract.Check.Require(index < _count, "out of bound index");
  553. if (index == --_count)
  554. return;
  555. Array.Copy(_buffer, index + 1, _buffer, index, _count - index);
  556. _buffer[_count] = default(T);
  557. }
  558. public void Resize(int newSize)
  559. {
  560. if (newSize < MIN_SIZE)
  561. newSize = MIN_SIZE;
  562. Array.Resize(ref _buffer, newSize);
  563. _count = newSize;
  564. }
  565. public void SetAt(int index, T value)
  566. {
  567. if (index >= _buffer.Length)
  568. AllocateMore(index + 1);
  569. if (_count <= index)
  570. _count = index + 1;
  571. this[index] = value;
  572. }
  573. public void Sort(IComparer<T> comparer)
  574. {
  575. Array.Sort(_buffer, 0, _count, comparer);
  576. }
  577. public T[] ToArray()
  578. {
  579. T[] destinationArray = new T[_count];
  580. Array.Copy(_buffer, 0, destinationArray, 0, _count);
  581. return destinationArray;
  582. }
  583. /// <summary>
  584. /// This function exists to allow fast iterations. The size of the array returned cannot be
  585. /// used. The list count must be used instead.
  586. /// </summary>
  587. /// <returns></returns>
  588. public T[] ToArrayFast()
  589. {
  590. return _buffer;
  591. }
  592. public bool UnorderedRemove(T item)
  593. {
  594. var index = IndexOf(item);
  595. if (index == -1)
  596. return false;
  597. UnorderedRemoveAt(index);
  598. return true;
  599. }
  600. public bool UnorderedRemoveAt(int index)
  601. {
  602. DesignByContract.Check.Require(index < _count && _count > 0, "out of bound index");
  603. if (index == --_count)
  604. {
  605. _buffer[_count] = default(T);
  606. return false;
  607. }
  608. _buffer[index] = _buffer[_count];
  609. _buffer[_count] = default(T);
  610. return true;
  611. }
  612. IEnumerator IEnumerable.GetEnumerator()
  613. {
  614. return GetEnumerator();
  615. }
  616. IEnumerator<T> IEnumerable<T>.GetEnumerator()
  617. {
  618. return GetEnumerator();
  619. }
  620. void AllocateMore()
  621. {
  622. var newList = new T[Math.Max(_buffer.Length << 1, MIN_SIZE)];
  623. if (_count > 0) _buffer.CopyTo(newList, 0);
  624. _buffer = newList;
  625. }
  626. void AllocateMore(int newSize)
  627. {
  628. var oldLength = Math.Max(_buffer.Length, MIN_SIZE);
  629. while (oldLength < newSize)
  630. oldLength <<= 1;
  631. var newList = new T[oldLength];
  632. if (_count > 0) Array.Copy(_buffer, newList, _count);
  633. _buffer = newList;
  634. }
  635. public void Trim()
  636. {
  637. if (_count < _buffer.Length)
  638. Resize(_count);
  639. }
  640. public bool Reuse<U>(int index, out U result)
  641. where U:class, T
  642. {
  643. result = default(U);
  644. if (index >= _buffer.Length)
  645. return false;
  646. result = (U)_buffer[index];
  647. return result != null;
  648. }
  649. T[] _buffer;
  650. int _count;
  651. public static class NoVirt
  652. {
  653. public static int Count(FasterList<T> fasterList)
  654. {
  655. return fasterList._count;
  656. }
  657. public static T[] ToArrayFast(FasterList<T> fasterList, out int count)
  658. {
  659. count = fasterList._count;
  660. return fasterList._buffer;
  661. }
  662. }
  663. }
  664. }