mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-17 14:14:17 +01:00
Fix ServiceScope.CreatePrivateScopedObject concurrency
This commit is contained in:
parent
4383a5747d
commit
32b24b3b5a
1 changed files with 34 additions and 26 deletions
|
|
@ -1,7 +1,10 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Concurrent;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
using Serilog;
|
||||||
|
|
||||||
namespace Dalamud.IoC.Internal;
|
namespace Dalamud.IoC.Internal;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -41,8 +44,8 @@ internal class ServiceScopeImpl : IServiceScope
|
||||||
{
|
{
|
||||||
private readonly ServiceContainer container;
|
private readonly ServiceContainer container;
|
||||||
|
|
||||||
private readonly List<object> privateScopedObjects = new();
|
private readonly List<object> privateScopedObjects = [];
|
||||||
private readonly List<object> scopeCreatedObjects = new();
|
private readonly ConcurrentDictionary<Type, Task<object?>> scopeCreatedObjects = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="ServiceScopeImpl" /> class.
|
/// Initializes a new instance of the <see cref="ServiceScopeImpl" /> class.
|
||||||
|
|
@ -77,26 +80,30 @@ internal class ServiceScopeImpl : IServiceScope
|
||||||
/// <param name="objectType">The type of object to create.</param>
|
/// <param name="objectType">The type of object to create.</param>
|
||||||
/// <param name="scopedObjects">Additional scoped objects.</param>
|
/// <param name="scopedObjects">Additional scoped objects.</param>
|
||||||
/// <returns>The created object, or null.</returns>
|
/// <returns>The created object, or null.</returns>
|
||||||
public async Task<object?> CreatePrivateScopedObject(Type objectType, params object[] scopedObjects)
|
public Task<object?> CreatePrivateScopedObject(Type objectType, params object[] scopedObjects) =>
|
||||||
{
|
this.scopeCreatedObjects.GetOrAdd(
|
||||||
var instance = this.scopeCreatedObjects.FirstOrDefault(x => x.GetType() == objectType);
|
objectType,
|
||||||
if (instance != null)
|
static (objectType, p) => p.Scope.container.CreateAsync(
|
||||||
return instance;
|
objectType,
|
||||||
|
p.Objects.Concat(p.Scope.privateScopedObjects).ToArray()),
|
||||||
instance =
|
(Scope: this, Objects: scopedObjects));
|
||||||
await this.container.CreateAsync(objectType, scopedObjects.Concat(this.privateScopedObjects).ToArray());
|
|
||||||
if (instance != null)
|
|
||||||
this.scopeCreatedObjects.Add(instance);
|
|
||||||
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
foreach (var createdObject in this.scopeCreatedObjects)
|
foreach (var objectTask in this.scopeCreatedObjects)
|
||||||
{
|
{
|
||||||
switch (createdObject)
|
objectTask.Value.ContinueWith(
|
||||||
|
static r =>
|
||||||
|
{
|
||||||
|
if (!r.IsCompletedSuccessfully)
|
||||||
|
{
|
||||||
|
if (r.Exception is { } e)
|
||||||
|
Log.Error(e, "{what}: Failed to load.", nameof(ServiceScopeImpl));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (r.Result)
|
||||||
{
|
{
|
||||||
case IInternalDisposableService d:
|
case IInternalDisposableService d:
|
||||||
d.DisposeService();
|
d.DisposeService();
|
||||||
|
|
@ -105,6 +112,7 @@ internal class ServiceScopeImpl : IServiceScope
|
||||||
d.Dispose();
|
d.Dispose();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue