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.

113 lines
3.1KB

  1. using System;
  2. using Svelto.Common;
  3. using Svelto.DataStructures;
  4. namespace Svelto.ECS
  5. {
  6. public struct Consumer<T> : IDisposable where T : unmanaged, IEntityComponent
  7. {
  8. internal Consumer(string name, uint capacity) : this()
  9. {
  10. unsafe
  11. {
  12. #if DEBUG && !PROFILE_SVELTO
  13. _name = name;
  14. #endif
  15. _ringBuffer = new RingBuffer<ValueTuple<T, EGID>>((int) capacity,
  16. #if DEBUG && !PROFILE_SVELTO
  17. _name
  18. #else
  19. string.Empty
  20. #endif
  21. );
  22. mustBeDisposed = MemoryUtilities.Alloc<bool>(1, Allocator.Persistent);
  23. *(bool*) mustBeDisposed = false;
  24. isActive = MemoryUtilities.Alloc<bool>(1, Allocator.Persistent);
  25. *(bool*) isActive = true;
  26. }
  27. }
  28. internal Consumer(ExclusiveGroupStruct group, string name, uint capacity) : this(name, capacity)
  29. {
  30. this.group = group;
  31. hasGroup = true;
  32. }
  33. internal void Enqueue(in T entity, in EGID egid)
  34. {
  35. unsafe
  36. {
  37. if (*(bool*)isActive)
  38. _ringBuffer.Enqueue((entity, egid));
  39. }
  40. }
  41. public bool TryDequeue(out T entity)
  42. {
  43. var tryDequeue = _ringBuffer.TryDequeue(out var values);
  44. entity = values.Item1;
  45. return tryDequeue;
  46. }
  47. //Note: it is correct to publish the EGID at the moment of the publishing, as the responsibility of
  48. //the publisher consumer is not tracking the real state of the entity in the database at the
  49. //moment of the consumption, but it's instead to store a copy of the entity at the moment of the publishing
  50. public bool TryDequeue(out T entity, out EGID id)
  51. {
  52. var tryDequeue = _ringBuffer.TryDequeue(out var values);
  53. entity = values.Item1;
  54. id = values.Item2;
  55. return tryDequeue;
  56. }
  57. public void Flush() { _ringBuffer.Reset(); }
  58. public void Dispose()
  59. {
  60. unsafe
  61. {
  62. *(bool*) mustBeDisposed = true;
  63. }
  64. }
  65. public uint Count() { return (uint) _ringBuffer.Count; }
  66. public void Free()
  67. {
  68. MemoryUtilities.Free(mustBeDisposed, Allocator.Persistent);
  69. MemoryUtilities.Free(isActive, Allocator.Persistent);
  70. }
  71. public void Pause()
  72. {
  73. unsafe
  74. {
  75. *(bool*) isActive = false;
  76. }
  77. }
  78. public void Resume()
  79. {
  80. unsafe
  81. {
  82. *(bool*) isActive = true;
  83. }
  84. }
  85. readonly RingBuffer<ValueTuple<T, EGID>> _ringBuffer;
  86. internal readonly ExclusiveGroupStruct group;
  87. internal readonly bool hasGroup;
  88. internal IntPtr isActive;
  89. internal IntPtr mustBeDisposed;
  90. #if DEBUG && !PROFILE_SVELTO
  91. readonly string _name;
  92. #endif
  93. }
  94. }