summaryrefslogtreecommitdiff
path: root/src/StardewModdingAPI/Framework
diff options
context:
space:
mode:
authorJesse Plamondon-Willard <github@jplamondonw.com>2017-04-26 18:25:59 -0400
committerJesse Plamondon-Willard <github@jplamondonw.com>2017-04-26 18:25:59 -0400
commit0cf15d36d9e6f5a40a16e17f3bd3d53682fe648c (patch)
tree5aaf4d8cc82b2da36132a332e55a70e876d2c8d0 /src/StardewModdingAPI/Framework
parent971bfd32d2f44d2fa1795807ce1ba1b700ff4f86 (diff)
downloadSMAPI-0cf15d36d9e6f5a40a16e17f3bd3d53682fe648c.tar.gz
SMAPI-0cf15d36d9e6f5a40a16e17f3bd3d53682fe648c.tar.bz2
SMAPI-0cf15d36d9e6f5a40a16e17f3bd3d53682fe648c.zip
revamp 'exit immediately' to abort ongoing SMAPI tasks
Diffstat (limited to 'src/StardewModdingAPI/Framework')
-rw-r--r--src/StardewModdingAPI/Framework/InternalExtensions.cs8
-rw-r--r--src/StardewModdingAPI/Framework/Monitor.cs31
-rw-r--r--src/StardewModdingAPI/Framework/SGame.cs7
3 files changed, 33 insertions, 13 deletions
diff --git a/src/StardewModdingAPI/Framework/InternalExtensions.cs b/src/StardewModdingAPI/Framework/InternalExtensions.cs
index a2d589ff..2f6f7490 100644
--- a/src/StardewModdingAPI/Framework/InternalExtensions.cs
+++ b/src/StardewModdingAPI/Framework/InternalExtensions.cs
@@ -41,6 +41,14 @@ namespace StardewModdingAPI.Framework
foreach (EventHandler handler in handlers.Cast<EventHandler>())
{
+ // handle SMAPI exiting
+ if (monitor.IsExiting)
+ {
+ monitor.Log($"SMAPI shutting down: aborting {name} event.", LogLevel.Warn);
+ return;
+ }
+
+ // raise event
try
{
handler.Invoke(sender, args ?? EventArgs.Empty);
diff --git a/src/StardewModdingAPI/Framework/Monitor.cs b/src/StardewModdingAPI/Framework/Monitor.cs
index dac81f14..925efc33 100644
--- a/src/StardewModdingAPI/Framework/Monitor.cs
+++ b/src/StardewModdingAPI/Framework/Monitor.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Threading;
using StardewModdingAPI.Framework.Logging;
namespace StardewModdingAPI.Framework
@@ -34,13 +35,16 @@ namespace StardewModdingAPI.Framework
[LogLevel.Alert] = ConsoleColor.Magenta
};
- /// <summary>A delegate which requests that SMAPI immediately exit the game. This should only be invoked when an irrecoverable fatal error happens that risks save corruption or game-breaking bugs.</summary>
- private readonly RequestExitDelegate RequestExit;
+ /// <summary>Propagates notification that SMAPI should exit.</summary>
+ private readonly CancellationTokenSource ExitTokenSource;
/*********
** Accessors
*********/
+ /// <summary>Whether SMAPI is aborting. Mods don't need to worry about this unless they have background tasks.</summary>
+ public bool IsExiting => this.ExitTokenSource.IsCancellationRequested;
+
/// <summary>Whether to show trace messages in the console.</summary>
internal bool ShowTraceInConsole { get; set; }
@@ -58,8 +62,8 @@ namespace StardewModdingAPI.Framework
/// <param name="source">The name of the module which logs messages using this instance.</param>
/// <param name="consoleManager">Manages access to the console output.</param>
/// <param name="logFile">The log file to which to write messages.</param>
- /// <param name="requestExitDelegate">A delegate which requests that SMAPI immediately exit the game.</param>
- public Monitor(string source, ConsoleInterceptionManager consoleManager, LogFileManager logFile, RequestExitDelegate requestExitDelegate)
+ /// <param name="exitTokenSource">Propagates notification that SMAPI should exit.</param>
+ public Monitor(string source, ConsoleInterceptionManager consoleManager, LogFileManager logFile, CancellationTokenSource exitTokenSource)
{
// validate
if (string.IsNullOrWhiteSpace(source))
@@ -69,7 +73,7 @@ namespace StardewModdingAPI.Framework
this.Source = source;
this.LogFile = logFile ?? throw new ArgumentNullException(nameof(logFile), "The log file manager cannot be null.");
this.ConsoleManager = consoleManager;
- this.RequestExit = requestExitDelegate;
+ this.ExitTokenSource = exitTokenSource;
}
/// <summary>Log a message for the player or developer.</summary>
@@ -84,14 +88,8 @@ namespace StardewModdingAPI.Framework
/// <param name="reason">The reason for the shutdown.</param>
public void ExitGameImmediately(string reason)
{
- this.RequestExit(this.Source, reason);
- }
-
- /// <summary>Log a fatal error message.</summary>
- /// <param name="message">The message to log.</param>
- internal void LogFatal(string message)
- {
- this.LogImpl(this.Source, message, LogLevel.Error, ConsoleColor.White, background: ConsoleColor.Red);
+ this.LogFatal($"{this.Source} requested an immediate game shutdown: {reason}");
+ this.ExitTokenSource.Cancel();
}
/// <summary>Log a message for the player or developer, using the specified console color.</summary>
@@ -109,6 +107,13 @@ namespace StardewModdingAPI.Framework
/*********
** Private methods
*********/
+ /// <summary>Log a fatal error message.</summary>
+ /// <param name="message">The message to log.</param>
+ private void LogFatal(string message)
+ {
+ this.LogImpl(this.Source, message, LogLevel.Error, ConsoleColor.White, background: ConsoleColor.Red);
+ }
+
/// <summary>Write a message line to the log.</summary>
/// <param name="source">The name of the mod logging the message.</param>
/// <param name="message">The message to log.</param>
diff --git a/src/StardewModdingAPI/Framework/SGame.cs b/src/StardewModdingAPI/Framework/SGame.cs
index 61493e87..e7c07889 100644
--- a/src/StardewModdingAPI/Framework/SGame.cs
+++ b/src/StardewModdingAPI/Framework/SGame.cs
@@ -200,6 +200,13 @@ namespace StardewModdingAPI.Framework
/// <param name="gameTime">A snapshot of the game timing state.</param>
protected override void Update(GameTime gameTime)
{
+ // SMAPI exiting, stop processing game updates
+ if (this.Monitor.IsExiting)
+ {
+ this.Monitor.Log("SMAPI shutting down: aborting update.", LogLevel.Trace);
+ return;
+ }
+
// While a background new-day task is in progress, the game skips its own update logic
// and defers to the XNA Update method. Running mod code in parallel to the background
// update is risky, because data changes can conflict (e.g. collection changed during