Skip to content

Commit 560dcd4

Browse files
committed
make gameenge disposable and cleanup FS handler
1 parent 58033e5 commit 560dcd4

5 files changed

Lines changed: 104 additions & 24 deletions

File tree

src/ModVerify/GameVerifyPipeline.cs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ internal sealed class GameVerifyPipeline : StepRunnerPipelineBase<AsyncStepRunne
3535
private readonly VerificationBaseline _baseline;
3636
private readonly SuppressionList _suppressions;
3737

38+
private IStarWarsGameEngineHandle? _gameEngine;
39+
3840
internal IReadOnlyCollection<VerificationError> Errors => [.._errors];
3941

4042
internal IReadOnlyCollection<IGameVerifierInfo> Verifiers => [.. _verifiers];
@@ -78,28 +80,27 @@ protected override async Task PrepareCoreAsync(CancellationToken token)
7880
_verifiers.Clear();
7981
_errors.Clear();
8082

81-
IStarWarsGameEngine gameEngine;
82-
8383
try
8484
{
8585
var engineService = ServiceProvider.GetRequiredService<IPetroglyphStarWarsGameEngineService>();
86-
gameEngine = await engineService.InitializeAsync(
86+
_gameEngine = await engineService.InitializeAsync(
8787
_verificationTarget.Engine,
8888
_verificationTarget.Location,
8989
_engineErrorReporter,
9090
_engineInitializationReporter,
9191
false,
92-
CancellationToken.None).ConfigureAwait(false);
92+
configureFileSystem:fs => fs.UseLiveVirtualStrategy(),
93+
cancellationToken: CancellationToken.None).ConfigureAwait(false);
9394
}
9495
catch (Exception e)
9596
{
9697
Logger?.LogError(e, "Creating game engine failed: {Message}", e.Message);
9798
throw;
9899
}
99100

100-
AddStep(new GameEngineErrorCollector(_engineErrorReporter, gameEngine, _serviceSettings.GameVerifySettings, ServiceProvider));
101+
AddStep(new GameEngineErrorCollector(_engineErrorReporter, _gameEngine, _serviceSettings.GameVerifySettings, ServiceProvider));
101102

102-
foreach (var gameVerificationStep in CreateVerifiers(gameEngine))
103+
foreach (var gameVerificationStep in CreateVerifiers(_gameEngine))
103104
AddStep(gameVerificationStep);
104105
}
105106

@@ -147,6 +148,8 @@ protected override void DisposeResources()
147148
_engineErrorReporter.Clear();
148149
_aggregatedVerifyProgressReporter?.Dispose();
149150
_aggregatedVerifyProgressReporter = null;
151+
_gameEngine?.Dispose();
152+
_gameEngine = null;
150153
}
151154

152155
private void AddStep(GameVerifier verifier)
Lines changed: 72 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
using System.Collections.Generic;
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Threading;
24
using PG.StarWarsGame.Engine.Audio.Sfx;
35
using PG.StarWarsGame.Engine.CommandBar;
46
using PG.StarWarsGame.Engine.GameConstants;
@@ -11,25 +13,83 @@
1113

1214
namespace PG.StarWarsGame.Engine;
1315

14-
internal sealed class GameEngine : IStarWarsGameEngine
16+
internal sealed class GameEngine : IStarWarsGameEngineHandle
1517
{
18+
private int _disposed;
19+
20+
private PetroglyphFileSystem? _pgFileSystem;
21+
1622
public required GameEngineType EngineType { get; init; }
1723

18-
public required IPGRender PGRender { get; init; }
24+
public required IPGRender PGRender
25+
{
26+
get { ThrowIfDisposed(); return field; }
27+
init;
28+
}
29+
30+
public required IFontManager FontManager
31+
{
32+
get { ThrowIfDisposed(); return field; }
33+
init;
34+
}
35+
36+
public required ICommandBarGameManager CommandBar
37+
{
38+
get { ThrowIfDisposed(); return field; }
39+
init;
40+
}
1941

20-
public required IFontManager FontManager { get; init; }
42+
public required IGameRepository GameRepository
43+
{
44+
get { ThrowIfDisposed(); return field; }
45+
init
46+
{
47+
field = value;
48+
_pgFileSystem = value.PGFileSystem;
49+
}
50+
}
2151

22-
public required ICommandBarGameManager CommandBar { get; init; }
52+
public required IGameConstants GameConstants
53+
{
54+
get { ThrowIfDisposed(); return field; }
55+
init;
56+
}
2357

24-
public required IGameRepository GameRepository { get; init; }
58+
public required IGuiDialogManager GuiDialogManager
59+
{
60+
get { ThrowIfDisposed(); return field; }
61+
init;
62+
}
2563

26-
public required IGameConstants GameConstants { get; init; }
64+
public required IGameObjectTypeGameManager GameObjectTypeManager
65+
{
66+
get { ThrowIfDisposed(); return field; }
67+
init;
68+
}
2769

28-
public required IGuiDialogManager GuiDialogManager { get; init; }
70+
public required ISfxEventGameManager SfxGameManager
71+
{
72+
get { ThrowIfDisposed(); return field; }
73+
init;
74+
}
2975

30-
public required IGameObjectTypeGameManager GameObjectTypeManager { get; init; }
76+
public required IEnumerable<LanguageType> InstalledLanguages
77+
{
78+
get { ThrowIfDisposed(); return field; }
79+
init;
80+
}
3181

32-
public required ISfxEventGameManager SfxGameManager { get; init; }
82+
public void Dispose()
83+
{
84+
if (Interlocked.Exchange(ref _disposed, 1) != 0)
85+
return;
86+
_pgFileSystem?.CleanupStrategy();
87+
_pgFileSystem = null;
88+
}
3389

34-
public required IEnumerable<LanguageType> InstalledLanguages { get; init; }
35-
}
90+
private void ThrowIfDisposed()
91+
{
92+
if (_disposed != 0)
93+
throw new ObjectDisposedException(nameof(GameEngine));
94+
}
95+
}
Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
1-
using System.Threading;
1+
using System;
2+
using System.Threading;
23
using System.Threading.Tasks;
34
using PG.StarWarsGame.Engine.ErrorReporting;
5+
using PG.StarWarsGame.Engine.IO;
46

57
namespace PG.StarWarsGame.Engine;
68

79
public interface IPetroglyphStarWarsGameEngineService
810
{
9-
public Task<IStarWarsGameEngine> InitializeAsync(
11+
public Task<IStarWarsGameEngineHandle> InitializeAsync(
1012
GameEngineType engineType,
1113
GameLocations gameLocations,
1214
IGameEngineErrorReporter? errorReporter = null,
13-
IGameEngineInitializationReporter? initReporter = null,
15+
IGameEngineInitializationReporter? initReporter = null,
1416
bool cancelOnInitializationError = false,
17+
Action<PetroglyphFileSystem>? configureFileSystem = null,
1518
CancellationToken cancellationToken = default);
1619
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using System;
2+
3+
namespace PG.StarWarsGame.Engine;
4+
5+
/// <summary>
6+
/// An owned reference to a <see cref="IStarWarsGameEngine"/> that controls its lifetime.
7+
/// Disposing this handle releases all resources held by the engine.
8+
/// </summary>
9+
public interface IStarWarsGameEngineHandle : IStarWarsGameEngine, IDisposable
10+
{
11+
}

src/PetroglyphTools/PG.StarWarsGame.Engine/PetroglyphStarWarsGameEngineService.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,13 @@ internal sealed class PetroglyphStarWarsGameEngineService(IServiceProvider servi
2323
private readonly ILogger? _logger = serviceProvider.GetService<ILoggerFactory>()
2424
?.CreateLogger(typeof(PetroglyphStarWarsGameEngineService));
2525

26-
public async Task<IStarWarsGameEngine> InitializeAsync(
26+
public async Task<IStarWarsGameEngineHandle> InitializeAsync(
2727
GameEngineType engineType,
2828
GameLocations gameLocations,
2929
IGameEngineErrorReporter? errorReporter = null,
3030
IGameEngineInitializationReporter? initReporter = null,
3131
bool cancelOnInitializationError = false,
32+
Action<PetroglyphFileSystem>? configureFileSystem = null,
3233
CancellationToken cancellationToken = default)
3334

3435
{
@@ -39,7 +40,7 @@ public async Task<IStarWarsGameEngine> InitializeAsync(
3940

4041
try
4142
{
42-
return await InitializeEngineAsync(engineType, gameLocations, errorListenerWrapper, initReporter, cts.Token)
43+
return await InitializeEngineAsync(engineType, gameLocations, errorListenerWrapper, initReporter, configureFileSystem, cts.Token)
4344
.ConfigureAwait(false);
4445
}
4546
finally
@@ -57,11 +58,12 @@ void OnInitializationError(object sender, InitializationError e)
5758
}
5859
}
5960

60-
private async Task<IStarWarsGameEngine> InitializeEngineAsync(
61+
private async Task<IStarWarsGameEngineHandle> InitializeEngineAsync(
6162
GameEngineType engineType,
6263
GameLocations gameLocations,
6364
GameEngineErrorReporterWrapper errorReporter,
6465
IGameEngineInitializationReporter? initReporter,
66+
Action<PetroglyphFileSystem>? configureFileSystem,
6567
CancellationToken token)
6668
{
6769
try
@@ -71,6 +73,7 @@ private async Task<IStarWarsGameEngine> InitializeEngineAsync(
7173

7274
var repoFactory = _serviceProvider.GetRequiredService<IGameRepositoryFactory>();
7375
var repository = repoFactory.Create(engineType, gameLocations, errorReporter);
76+
configureFileSystem?.Invoke(repository.PGFileSystem);
7477

7578
var pgRender = new PGRender(repository, errorReporter, serviceProvider);
7679

0 commit comments

Comments
 (0)