add boot completion service
This commit is contained in:
@@ -1,166 +1,150 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Bootstrap
|
||||
{
|
||||
/// <summary>
|
||||
/// A service that provides information about the boot completion status
|
||||
/// and allows systems to register for callbacks when boot is complete.
|
||||
/// Service that provides notification and management of boot completion status.
|
||||
/// Allows systems to subscribe to boot completion events, register initialization actions with priorities,
|
||||
/// or await boot completion asynchronously.
|
||||
/// </summary>
|
||||
public static class BootCompletionService
|
||||
{
|
||||
/// <summary>
|
||||
/// True if the boot process has fully completed
|
||||
/// Indicates if the boot process has completed
|
||||
/// </summary>
|
||||
public static bool IsBootComplete { get; private set; }
|
||||
public static bool IsBootComplete { get; private set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Timestamp when the boot completed (Time.realtimeSinceStartup)
|
||||
/// </summary>
|
||||
public static float BootCompletionTime { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Event triggered when boot process completes.
|
||||
/// Will be triggered immediately for new subscribers if boot is already complete.
|
||||
/// Event triggered when boot completes
|
||||
/// </summary>
|
||||
public static event Action OnBootComplete;
|
||||
|
||||
/// <summary>
|
||||
/// Actions to be executed in a specific order once boot completes
|
||||
/// Represents an initialization action with priority
|
||||
/// </summary>
|
||||
private static readonly List<OrderedInitAction> _orderedInitActions = new List<OrderedInitAction>();
|
||||
|
||||
/// <summary>
|
||||
/// Task completion source for async boot completion waiting
|
||||
/// </summary>
|
||||
private static TaskCompletionSource<bool> _bootCompletionTask;
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the service - called by CustomBoot
|
||||
/// </summary>
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)]
|
||||
private static void Initialize()
|
||||
private class InitializationAction
|
||||
{
|
||||
// Reset state
|
||||
IsBootComplete = false;
|
||||
_bootCompletionTask = new TaskCompletionSource<bool>();
|
||||
public Action Action { get; }
|
||||
public int Priority { get; }
|
||||
public string Name { get; }
|
||||
|
||||
// Subscribe to CustomBoot completion event
|
||||
CustomBoot.OnBootCompleted += HandleBootCompleted;
|
||||
|
||||
Debug.Log("[BootCompletionService] Initialized and waiting for boot completion");
|
||||
public InitializationAction(Action action, int priority, string name)
|
||||
{
|
||||
Action = action;
|
||||
Priority = priority;
|
||||
Name = name;
|
||||
}
|
||||
}
|
||||
|
||||
// List of initialization actions to be executed once boot completes
|
||||
private static List<InitializationAction> _initializationActions = new List<InitializationAction>();
|
||||
|
||||
// TaskCompletionSource for async await pattern
|
||||
private static TaskCompletionSource<bool> _bootCompletionTask = new TaskCompletionSource<bool>();
|
||||
|
||||
/// <summary>
|
||||
/// Handler for when CustomBoot reports completion
|
||||
/// Called by CustomBoot when the boot process is complete
|
||||
/// </summary>
|
||||
private static void HandleBootCompleted()
|
||||
internal static void HandleBootCompleted()
|
||||
{
|
||||
if (IsBootComplete) return; // Avoid duplicate triggers
|
||||
if (IsBootComplete)
|
||||
return;
|
||||
|
||||
IsBootComplete = true;
|
||||
BootCompletionTime = Time.realtimeSinceStartup;
|
||||
|
||||
Debug.Log($"[BootCompletionService] Boot completed at {BootCompletionTime:F2}s since startup");
|
||||
Debug.Log("[BootCompletionService] Boot process completed, executing initialization actions");
|
||||
|
||||
// Execute ordered initialization actions
|
||||
ExecuteOrderedInitActions();
|
||||
|
||||
// Complete the task
|
||||
_bootCompletionTask.TrySetResult(true);
|
||||
// Execute initialization actions in priority order (lower number = higher priority)
|
||||
ExecuteInitializationActions();
|
||||
|
||||
// Trigger the event
|
||||
OnBootComplete?.Invoke();
|
||||
|
||||
// Complete the task for async waiters
|
||||
_bootCompletionTask.TrySetResult(true);
|
||||
|
||||
Debug.Log("[BootCompletionService] All boot completion handlers executed");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Execute the registered ordered initialization actions
|
||||
/// </summary>
|
||||
private static void ExecuteOrderedInitActions()
|
||||
{
|
||||
// Sort actions by priority
|
||||
_orderedInitActions.Sort((a, b) => a.Priority.CompareTo(b.Priority));
|
||||
|
||||
foreach (var action in _orderedInitActions)
|
||||
{
|
||||
try
|
||||
{
|
||||
Debug.Log($"[BootCompletionService] Executing priority {action.Priority} initialization: {action.Name}");
|
||||
action.Action?.Invoke();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError($"[BootCompletionService] Error executing initialization action '{action.Name}': {e.Message}\n{e.StackTrace}");
|
||||
}
|
||||
}
|
||||
|
||||
// Clear the list after execution
|
||||
_orderedInitActions.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register an action to be executed when boot is complete.
|
||||
/// If boot is already complete, the action will execute immediately.
|
||||
/// Register an action to be executed when boot completes.
|
||||
/// Lower priority numbers run first.
|
||||
/// </summary>
|
||||
/// <param name="action">The action to execute</param>
|
||||
/// <param name="priority">Lower numbers execute first (default: 100)</param>
|
||||
/// <param name="name">Optional name for debugging</param>
|
||||
/// <param name="priority">Priority (lower numbers run first)</param>
|
||||
/// <param name="name">Name for debugging</param>
|
||||
public static void RegisterInitAction(Action action, int priority = 100, string name = null)
|
||||
{
|
||||
if (action == null) return;
|
||||
if (action == null)
|
||||
return;
|
||||
|
||||
name = name ?? $"Anonymous_{_orderedInitActions.Count}";
|
||||
if (string.IsNullOrEmpty(name))
|
||||
name = $"Action_{_initializationActions.Count}";
|
||||
|
||||
var initAction = new InitializationAction(action, priority, name);
|
||||
|
||||
if (IsBootComplete)
|
||||
{
|
||||
// Boot already completed, execute immediately
|
||||
Debug.Log($"[BootCompletionService] Executing late initialization: {name} (boot already complete)");
|
||||
// If boot is already complete, execute immediately
|
||||
Debug.Log($"[BootCompletionService] Executing late registration: {name} (Priority: {priority})");
|
||||
try
|
||||
{
|
||||
action.Invoke();
|
||||
action();
|
||||
}
|
||||
catch (Exception e)
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"[BootCompletionService] Error executing late initialization action '{name}': {e.Message}\n{e.StackTrace}");
|
||||
Debug.LogError($"[BootCompletionService] Error executing init action '{name}': {ex}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add to ordered list
|
||||
_orderedInitActions.Add(new OrderedInitAction
|
||||
{
|
||||
Action = action,
|
||||
Priority = priority,
|
||||
Name = name
|
||||
});
|
||||
Debug.Log($"[BootCompletionService] Registered initialization action: {name} with priority {priority}");
|
||||
// Otherwise add to the queue
|
||||
_initializationActions.Add(initAction);
|
||||
Debug.Log($"[BootCompletionService] Registered init action: {name} (Priority: {priority})");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a task that completes when the boot process is complete.
|
||||
/// If boot is already complete, returns a completed task.
|
||||
/// Wait asynchronously for boot completion
|
||||
/// </summary>
|
||||
/// <returns>Task that completes when boot is complete</returns>
|
||||
public static Task WaitForBootCompletionAsync()
|
||||
{
|
||||
if (IsBootComplete)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
|
||||
return _bootCompletionTask.Task;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Structure for ordered initialization actions
|
||||
/// Execute all registered initialization actions in priority order
|
||||
/// </summary>
|
||||
private class OrderedInitAction
|
||||
private static void ExecuteInitializationActions()
|
||||
{
|
||||
public Action Action;
|
||||
public int Priority;
|
||||
public string Name;
|
||||
// Sort by priority (lowest first)
|
||||
var sortedActions = _initializationActions
|
||||
.OrderBy(a => a.Priority)
|
||||
.ToList();
|
||||
|
||||
foreach (var action in sortedActions)
|
||||
{
|
||||
try
|
||||
{
|
||||
Debug.Log($"[BootCompletionService] Executing: {action.Name} (Priority: {action.Priority})");
|
||||
action.Action();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"[BootCompletionService] Error executing init action '{action.Name}': {ex}");
|
||||
}
|
||||
}
|
||||
|
||||
// Clear the list after execution
|
||||
_initializationActions.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user