// Copyright (c) Craftwork Games. All rights reserved.
// Licensed under the MIT license.
// See LICENSE file in the project root for full license information.
using System.Collections.Generic;
using TPL = System.Threading.Tasks.Parallel;
namespace MonoGame.Extended.Particles.Modifiers;
///
/// Defines different strategies for executing particle modifiers within a particle system.
///
///
/// The strategy pattern implemented by this class allows the particle system to switch
/// between serial (single-threaded) and parallel (multi-threaded) execution methods
/// to optimize performance based on the execution environment and particle workload.
///
public abstract class ModifierExecutionStrategy
{
///
/// Gets a singleton instance of the serial execution strategy.
///
///
/// The serial strategy processes each modifier one after another on a single thread.
/// This may be more efficient for small particle counts or when thread synchronization
/// overhead outweighs the benefits of parallelism.
///
static public ModifierExecutionStrategy Serial = new SerialModifierExecutionStrategy();
///
/// Gets a singleton instance of the parallel execution strategy.
///
///
/// The parallel strategy processes modifiers concurrently using multiple threads.
/// This can significantly improve performance for systems with many particles and
/// multiple modifiers, especially on multi-core processors.
///
static public ModifierExecutionStrategy Parallel = new ParallelModifierExecutionStrategy();
///
/// Executes all modifiers in the collection on the particle buffer using the implemented strategy.
///
/// The collection of modifiers to execute.
/// The elapsed time, in seconds, since the last update.
/// The iterator used to iterate the particles.
internal abstract unsafe void ExecuteModifiers(List modifiers, float elapsedSeconds, ParticleIterator iterator);
///
/// Implements a serial (single-threaded) execution strategy for particle modifiers.
///
///
/// This strategy processes each modifier sequentially on a single thread,
/// which can be more efficient for smaller particle counts or when the
/// overhead of thread synchronization would outweigh the benefits of parallelism.
///
internal class SerialModifierExecutionStrategy : ModifierExecutionStrategy
{
internal override unsafe void ExecuteModifiers(List modifiers, float elapsedSeconds, ParticleIterator iterator)
{
for (int i = 0; i < modifiers.Count; i++)
{
modifiers[i].Update(elapsedSeconds, iterator.Reset());
}
}
public override string ToString()
{
return nameof(Serial);
}
}
///
/// Implements a parallel (multi-threaded) execution strategy for particle modifiers.
///
///
/// This strategy processes modifiers concurrently. It can significantly improve
/// performance for systems with many particles and multiple modifiers.
///
internal class ParallelModifierExecutionStrategy : ModifierExecutionStrategy
{
internal override unsafe void ExecuteModifiers(List modifiers, float elapsedSeconds, ParticleIterator iterator)
{
TPL.ForEach(modifiers, modifier => modifier.Update(elapsedSeconds, iterator.Reset()));
}
public override string ToString()
{
return nameof(Parallel);
}
}
}