Pool.cs 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. using System;
  2. using System.Collections.Generic;
  3. namespace Asset_Cleaner {
  4. class Pool<T> : IDisposable where T : class {
  5. Func<T> _ctor;
  6. readonly Stack<T> _stack;
  7. // todo place asserts on app quit
  8. Action<T> _reset;
  9. Action<T> _destroy;
  10. static Action<T> Empty = _ => { };
  11. public Pool(Func<T> ctor, Action<T> reset, Action<T> destroy = null) {
  12. _ctor = ctor;
  13. #if !M_DISABLE_POOLING
  14. _destroy = destroy ?? Empty;
  15. _reset = reset;
  16. _stack = new Stack<T>();
  17. #endif
  18. }
  19. public T Get() {
  20. #if M_DISABLE_POOLING
  21. return _ctor.Invoke();
  22. #else
  23. T element;
  24. if (_stack.Count == 0) {
  25. element = _ctor();
  26. }
  27. else {
  28. element = _stack.Pop();
  29. }
  30. return element;
  31. #endif
  32. }
  33. public void Release(ref T element) {
  34. #if !M_DISABLE_POOLING
  35. Asr.IsFalse(_stack.Count > 0 && ReferenceEquals(_stack.Peek(), element),
  36. "Internal error. Trying to release object that is already released to pool. ");
  37. _reset.Invoke(element);
  38. _stack.Push(element);
  39. #endif
  40. element = null;
  41. }
  42. public void Dispose() {
  43. #if !M_DISABLE_POOLING
  44. while (_stack.Count > 0) {
  45. var t = _stack.Pop();
  46. _destroy.Invoke(t);
  47. }
  48. #endif
  49. }
  50. public _Scope GetScoped(out T tmp) {
  51. tmp = Get();
  52. return new _Scope(this, ref tmp);
  53. }
  54. public struct _Scope : IDisposable {
  55. Pool<T> _pool;
  56. T _val;
  57. internal _Scope(Pool<T> pool, ref T val) {
  58. _pool = pool;
  59. _val = val;
  60. }
  61. public void Dispose() {
  62. _pool.Release(ref _val);
  63. }
  64. }
  65. }
  66. }