// --------------------------------------------------------------------------------------------------------------------
//
// Copyright (c) VRMADA, All rights reserved.
//
// --------------------------------------------------------------------------------------------------------------------
using System;
using System.Threading;
using System.Threading.Tasks;
using UltimateXR.Core.Threading.TaskControllers;
using UnityEngine;
namespace UltimateXR.Extensions.System.Threading
{
///
/// extensions.
///
public static class ActionExt
{
#region Public Methods
///
/// Executes repeatedly this , in the main thread, at until cancellation
/// is requested with .
///
/// to loop at Hz
/// Loop frequency in Hz
/// Cancellation token
///
///
public static async void Loop(this Action self, float rate = 10f, CancellationToken ct = default)
{
if (ct.IsCancellationRequested)
{
return;
}
int deltaTimeMs = Mathf.RoundToInt(1000f / rate);
while (!ct.IsCancellationRequested)
{
// Start delay timer parallel to action execution
Task delayTask = TaskExt.Delay(deltaTimeMs, ct);
self();
await delayTask;
}
}
///
/// Executes repeatedly this , in a separated thread, at Hz until
/// cancellation is requested using .
///
/// to loop at Hz
/// Loop frequency in Hz
/// Cancellation token
public static async void LoopThreaded(this Action self, float rate = 10f, CancellationToken ct = default)
{
if (ct.IsCancellationRequested)
{
return;
}
int deltaTimeMs = Mathf.RoundToInt(1000f / rate);
while (!ct.IsCancellationRequested)
{
// We don't want to abort current thread (Task.Run) with ct
// Instead, we wait for action to end, breaking the loop after that.
Task delayTask = TaskExt.Delay(deltaTimeMs, ct);
Task runTask = Task.Run(self, CancellationToken.None);
await Task.WhenAll(delayTask, runTask);
}
}
///
/// Creates a which wraps a cancellable loop executing this in
/// the main thread.
///
/// to loop at Hz
/// Loop frequency in Hz
///
/// Delay in milliseconds before loop executes its first iteration.
///
/// -
/// Equal or greater than zero: tells to automatically start looping
/// milliseconds after creation.
///
/// -
/// Negative (default) needs to be called on returned
/// to start looping.
///
///
///
///
/// A to handle (,
/// ) the loop execution.
///
///
///
///
public static UxrLoopController ToLoop(this Action self, float rate = 10f, int autoStartDelay = -1)
{
return new UxrLoopController(ct => Loop(self, rate, ct), autoStartDelay);
}
///
/// Creates a which wraps a cancellable loop executing this in a
/// separate thread.
///
/// to loop, in a separate thread, at Hz
/// Loop frequency in Hz
///
/// Delay in milliseconds before loop executes its first iteration.
///
/// -
/// Equal or greater than zero: tells to automatically start looping
/// milliseconds after creation.
///
/// -
/// Negative (default) needs to be called on returned
/// to start looping.
///
///
///
///
/// A to handle (,
/// ) the loop execution.
///
///
///
public static UxrLoopController ToThreadedLoop(this Action self, float rate = 10f, int autoStartDelay = -1)
{
return new UxrLoopController(ct => LoopThreaded(self, rate, ct), autoStartDelay);
}
#endregion
}
}