diff --git a/src/Lynx/Bench.cs b/src/Lynx/Bench.cs index 0aadf15a..8f321c56 100644 --- a/src/Lynx/Bench.cs +++ b/src/Lynx/Bench.cs @@ -129,11 +129,6 @@ public partial class Engine _engineWriter.TryWrite($"Total time: {Utils.CalculateUCITime(totalSeconds)}"); - // Cleanup game - NewGame(); - _isNewGameComing = false; - _isNewGameCommandSupported = false; - return (totalNodes, Utils.CalculateNps(totalNodes, totalSeconds)); } diff --git a/src/Lynx/Engine.cs b/src/Lynx/Engine.cs index bc67de88..cda10fb5 100644 --- a/src/Lynx/Engine.cs +++ b/src/Lynx/Engine.cs @@ -7,7 +7,7 @@ namespace Lynx; -public sealed partial class Engine +public sealed partial class Engine : IDisposable { internal const int DefaultMaxDepth = 5; @@ -15,6 +15,8 @@ public sealed partial class Engine private readonly ChannelWriter _engineWriter; private readonly TranspositionTable _tt; + private bool _disposedValue; + private bool _isSearching; /// @@ -78,13 +80,8 @@ public Engine(ChannelWriter engineWriter, TranspositionTable tt) _engineWriter = engineWriter; - // No need for ResetEngine() call here, WarmupEngine -> Bench -> NewGame() calls it + NewGame(); #endif - -#pragma warning disable S1215 // "GC.Collect" should not be called - GC.Collect(); - GC.WaitForPendingFinalizers(); -#pragma warning restore S1215 // "GC.Collect" should not be called } #pragma warning disable S1144 // Unused private types or members should be removed - used in Release mode @@ -93,8 +90,6 @@ private void WarmupEngine() _logger.Info("Warming up engine"); var sw = Stopwatch.StartNew(); - InitializeStaticClasses(); - const string goWarmupCommand = "go depth 10"; // ~300 ms var command = new GoCommand(goWarmupCommand); @@ -143,11 +138,6 @@ public void NewGame() _stopRequested = false; ResetEngine(); - -#pragma warning disable S1215 // "GC.Collect" should not be called - GC.Collect(); - GC.WaitForPendingFinalizers(); -#pragma warning restore S1215 // "GC.Collect" should not be called } [SkipLocalsInit] @@ -303,14 +293,29 @@ public void StopSearching() _absoluteSearchCancellationTokenSource.Cancel(); } - private static void InitializeStaticClasses() + public void FreeResources() + { + Game.FreeResources(); + + _disposedValue = true; + } + + private void Dispose(bool disposing) + { + if (!_disposedValue) + { + if (disposing) + { + FreeResources(); + } + _disposedValue = true; + } + } + + public void Dispose() { - _ = PVTable.Indexes[0]; - _ = Attacks.KingAttacks; - _ = ZobristTable.SideHash(); - _ = Masks.FileMasks; - _ = EvaluationConstants.HistoryBonus[1]; - _ = MoveGenerator.Init(); - _ = GoCommand.Init(); + // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method + Dispose(disposing: true); + GC.SuppressFinalize(this); } } diff --git a/src/Lynx/Searcher.cs b/src/Lynx/Searcher.cs index e0735ac8..e681dcf7 100644 --- a/src/Lynx/Searcher.cs +++ b/src/Lynx/Searcher.cs @@ -27,6 +27,8 @@ public Searcher(ChannelReader uciReader, ChannelWriter engineWri _engine = new Engine(_engineWriter, _ttWrapper); _logger = LogManager.GetCurrentClassLogger(); + + InitializeStaticClasses(); } public async Task Run(CancellationToken cancellationToken) @@ -97,6 +99,11 @@ public void NewGame() } _engine.NewGame(); + +#pragma warning disable S1215 // "GC.Collect" should not be called + GC.Collect(); + GC.WaitForPendingFinalizers(); +#pragma warning restore S1215 // "GC.Collect" should not be called } public void Quit() @@ -113,4 +120,15 @@ public async ValueTask RunBench(int depth) var results = _engine.Bench(depth); await _engine.PrintBenchResults(results); } + + private static void InitializeStaticClasses() + { + _ = PVTable.Indexes[0]; + _ = Attacks.KingAttacks; + _ = ZobristTable.SideHash(); + _ = Masks.FileMasks; + _ = EvaluationConstants.HistoryBonus[1]; + _ = MoveGenerator.Init(); + _ = GoCommand.Init(); + } }