mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-15 05:04:15 +01:00
Add call-on-services-ready attribute for service methods, and fix scene nullability (#900)
This commit is contained in:
parent
5809accf5d
commit
3369f569fb
52 changed files with 274 additions and 273 deletions
|
|
@ -6,7 +6,6 @@ using System.Reflection;
|
|||
using System.Threading.Tasks;
|
||||
using Dalamud.Configuration.Internal;
|
||||
using Dalamud.Game;
|
||||
using Dalamud.Interface.Internal;
|
||||
using Dalamud.IoC.Internal;
|
||||
using Dalamud.Logging.Internal;
|
||||
using Dalamud.Utility.Timing;
|
||||
|
|
@ -67,7 +66,6 @@ namespace Dalamud
|
|||
|
||||
var earlyLoadingServices = new HashSet<Type>();
|
||||
var blockingEarlyLoadingServices = new HashSet<Type>();
|
||||
var afterDrawingEarlyLoadedServices = new HashSet<Type>();
|
||||
|
||||
var dependencyServicesMap = new Dictionary<Type, List<Type>>();
|
||||
var getAsyncTaskMap = new Dictionary<Type, Task>();
|
||||
|
|
@ -90,10 +88,6 @@ namespace Dalamud
|
|||
getAsyncTaskMap[serviceType] = getTask;
|
||||
blockingEarlyLoadingServices.Add(serviceType);
|
||||
}
|
||||
else if (attr.IsAssignableTo(typeof(AfterDrawingEarlyLoadedService)))
|
||||
{
|
||||
afterDrawingEarlyLoadedServices.Add(serviceType);
|
||||
}
|
||||
else
|
||||
{
|
||||
earlyLoadingServices.Add(serviceType);
|
||||
|
|
@ -126,55 +120,44 @@ namespace Dalamud
|
|||
|
||||
try
|
||||
{
|
||||
for (var i = 0; i < 2; i++)
|
||||
var tasks = new List<Task>();
|
||||
var servicesToLoad = new HashSet<Type>();
|
||||
servicesToLoad.UnionWith(earlyLoadingServices);
|
||||
servicesToLoad.UnionWith(blockingEarlyLoadingServices);
|
||||
|
||||
while (servicesToLoad.Any())
|
||||
{
|
||||
var tasks = new List<Task>();
|
||||
var servicesToLoad = new HashSet<Type>();
|
||||
if (i == 0)
|
||||
foreach (var serviceType in servicesToLoad)
|
||||
{
|
||||
servicesToLoad.UnionWith(earlyLoadingServices);
|
||||
servicesToLoad.UnionWith(blockingEarlyLoadingServices);
|
||||
if (dependencyServicesMap[serviceType].Any(
|
||||
x => getAsyncTaskMap.GetValueOrDefault(x)?.IsCompleted == false))
|
||||
continue;
|
||||
|
||||
tasks.Add((Task)service.MakeGenericType(serviceType).InvokeMember(
|
||||
"StartLoader",
|
||||
BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.Public,
|
||||
null,
|
||||
null,
|
||||
null));
|
||||
servicesToLoad.Remove(serviceType);
|
||||
}
|
||||
|
||||
if (!tasks.Any())
|
||||
throw new InvalidOperationException("Unresolvable dependency cycle detected");
|
||||
|
||||
if (servicesToLoad.Any())
|
||||
{
|
||||
await Task.WhenAny(tasks);
|
||||
var faultedTasks = tasks.Where(x => x.IsFaulted).Select(x => (Exception)x.Exception!).ToArray();
|
||||
if (faultedTasks.Any())
|
||||
throw new AggregateException(faultedTasks);
|
||||
}
|
||||
else
|
||||
{
|
||||
servicesToLoad.UnionWith(afterDrawingEarlyLoadedServices);
|
||||
await (await Service<InterfaceManager>.GetAsync()).SceneInitializeTask;
|
||||
await Task.WhenAll(tasks);
|
||||
}
|
||||
|
||||
while (servicesToLoad.Any())
|
||||
{
|
||||
foreach (var serviceType in servicesToLoad)
|
||||
{
|
||||
if (dependencyServicesMap[serviceType].Any(
|
||||
x => getAsyncTaskMap.GetValueOrDefault(x)?.IsCompleted == false))
|
||||
continue;
|
||||
|
||||
tasks.Add((Task)service.MakeGenericType(serviceType).InvokeMember(
|
||||
"StartLoader",
|
||||
BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.Public,
|
||||
null,
|
||||
null,
|
||||
null));
|
||||
servicesToLoad.Remove(serviceType);
|
||||
}
|
||||
|
||||
if (!tasks.Any())
|
||||
throw new InvalidOperationException("Unresolvable dependency cycle detected");
|
||||
|
||||
if (servicesToLoad.Any())
|
||||
{
|
||||
await Task.WhenAny(tasks);
|
||||
var faultedTasks = tasks.Where(x => x.IsFaulted).Select(x => (Exception)x.Exception!).ToArray();
|
||||
if (faultedTasks.Any())
|
||||
throw new AggregateException(faultedTasks);
|
||||
}
|
||||
else
|
||||
{
|
||||
await Task.WhenAll(tasks);
|
||||
}
|
||||
|
||||
tasks.RemoveAll(x => x.IsCompleted);
|
||||
}
|
||||
tasks.RemoveAll(x => x.IsCompleted);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
|
|
@ -236,11 +219,11 @@ namespace Dalamud
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the class is a service, and will be instantiated automatically on startup,
|
||||
/// when drawing becomes available.
|
||||
/// Indicates that the method should be called when the services given in the constructor are ready.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public class AfterDrawingEarlyLoadedService : EarlyLoadedService
|
||||
[AttributeUsage(AttributeTargets.Method)]
|
||||
[MeansImplicitUse]
|
||||
public class CallWhenServicesReady : Attribute
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue