ModifierExecutionStrategy.cs 3.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. // Copyright (c) Craftwork Games. All rights reserved.
  2. // Licensed under the MIT license.
  3. // See LICENSE file in the project root for full license information.
  4. using System.Collections.Generic;
  5. using TPL = System.Threading.Tasks.Parallel;
  6. namespace MonoGame.Extended.Particles.Modifiers;
  7. /// <summary>
  8. /// Defines different strategies for executing particle modifiers within a particle system.
  9. /// </summary>
  10. /// <remarks>
  11. /// The strategy pattern implemented by this class allows the particle system to switch
  12. /// between serial (single-threaded) and parallel (multi-threaded) execution methods
  13. /// to optimize performance based on the execution environment and particle workload.
  14. /// </remarks>
  15. public abstract class ModifierExecutionStrategy
  16. {
  17. /// <summary>
  18. /// Gets a singleton instance of the serial execution strategy.
  19. /// </summary>
  20. /// <remarks>
  21. /// The serial strategy processes each modifier one after another on a single thread.
  22. /// This may be more efficient for small particle counts or when thread synchronization
  23. /// overhead outweighs the benefits of parallelism.
  24. /// </remarks>
  25. static public ModifierExecutionStrategy Serial = new SerialModifierExecutionStrategy();
  26. /// <summary>
  27. /// Gets a singleton instance of the parallel execution strategy.
  28. /// </summary>
  29. /// <remarks>
  30. /// The parallel strategy processes modifiers concurrently using multiple threads.
  31. /// This can significantly improve performance for systems with many particles and
  32. /// multiple modifiers, especially on multi-core processors.
  33. /// </remarks>
  34. static public ModifierExecutionStrategy Parallel = new ParallelModifierExecutionStrategy();
  35. /// <summary>
  36. /// Executes all modifiers in the collection on the particle buffer using the implemented strategy.
  37. /// </summary>
  38. /// <param name="modifiers">The collection of modifiers to execute.</param>
  39. /// <param name="elapsedSeconds">The elapsed time, in seconds, since the last update.</param>
  40. /// <param name="iterator">The iterator used to iterate the particles.</param>
  41. internal abstract unsafe void ExecuteModifiers(List<Modifier> modifiers, float elapsedSeconds, ParticleIterator iterator);
  42. /// <summary>
  43. /// Implements a serial (single-threaded) execution strategy for particle modifiers.
  44. /// </summary>
  45. /// <remarks>
  46. /// This strategy processes each modifier sequentially on a single thread,
  47. /// which can be more efficient for smaller particle counts or when the
  48. /// overhead of thread synchronization would outweigh the benefits of parallelism.
  49. /// </remarks>
  50. internal class SerialModifierExecutionStrategy : ModifierExecutionStrategy
  51. {
  52. internal override unsafe void ExecuteModifiers(List<Modifier> modifiers, float elapsedSeconds, ParticleIterator iterator)
  53. {
  54. for (int i = 0; i < modifiers.Count; i++)
  55. {
  56. modifiers[i].Update(elapsedSeconds, iterator.Reset());
  57. }
  58. }
  59. public override string ToString()
  60. {
  61. return nameof(Serial);
  62. }
  63. }
  64. /// <summary>
  65. /// Implements a parallel (multi-threaded) execution strategy for particle modifiers.
  66. /// </summary>
  67. /// <remarks>
  68. /// This strategy processes modifiers concurrently. It can significantly improve
  69. /// performance for systems with many particles and multiple modifiers.
  70. /// </remarks>
  71. internal class ParallelModifierExecutionStrategy : ModifierExecutionStrategy
  72. {
  73. internal override unsafe void ExecuteModifiers(List<Modifier> modifiers, float elapsedSeconds, ParticleIterator iterator)
  74. {
  75. TPL.ForEach(modifiers, modifier => modifier.Update(elapsedSeconds, iterator.Reset()));
  76. }
  77. public override string ToString()
  78. {
  79. return nameof(Parallel);
  80. }
  81. }
  82. }