From dca60f42b2048d6b0b27517b9e7686665e61e9c2 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Tue, 31 Dec 2019 16:18:11 -0500 Subject: fix XNA keeping loaded assets alive forever (#685) --- docs/release-notes.md | 2 ++ src/SMAPI/Framework/ContentManagers/BaseContentManager.cs | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/docs/release-notes.md b/docs/release-notes.md index 0ce79d9b..9ac95d86 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -9,6 +9,8 @@ * The 'skipped mods' list now shows broken dependencies first, so it's easier to see which ones to fix first. * Fixed compatibility with Linux Mint 18 (thanks to techge!) and Arch Linux. * Fixed compatibility with Linux systems which have libhybris-utils installed. + * Fixed memory leak when repeatedly loading a save and returning to title. + * Fixed memory leak when mods reload assets. * Fixes for the bundled Console Commands mod: * added new clothing items; * fixed spawning new flooring and rings (thanks to Mizzion!); diff --git a/src/SMAPI/Framework/ContentManagers/BaseContentManager.cs b/src/SMAPI/Framework/ContentManagers/BaseContentManager.cs index 41ce7c37..36f2f650 100644 --- a/src/SMAPI/Framework/ContentManagers/BaseContentManager.cs +++ b/src/SMAPI/Framework/ContentManagers/BaseContentManager.cs @@ -41,6 +41,10 @@ namespace StardewModdingAPI.Framework.ContentManagers /// A list of disposable assets. private readonly List> Disposables = new List>(); + /// The disposable assets tracked by the base content manager. + /// This should be kept empty to avoid keeping disposable assets referenced forever, which prevents garbage collection when they're unused. Disposable assets are tracked by instead, which avoids a hard reference. + private readonly List BaseDisposableReferences; + /********* ** Accessors @@ -84,6 +88,7 @@ namespace StardewModdingAPI.Framework.ContentManagers // get asset data this.LanguageCodes = this.GetKeyLocales().ToDictionary(p => p.Value, p => p.Key, StringComparer.InvariantCultureIgnoreCase); + this.BaseDisposableReferences = reflection.GetField>(this, "disposableAssets").GetValue(); } /// Load an asset that has been processed by the content pipeline. @@ -276,6 +281,9 @@ namespace StardewModdingAPI.Framework.ContentManagers assetName = this.AssertAndNormalizeAssetName(assetName); this.Cache[assetName] = value; } + + // avoid hard disposable references; see remarks on the field + this.BaseDisposableReferences.Clear(); } /// Parse a cache key into its component parts. -- cgit