avoid unneeded overhead of ConcurrentQueue
This commit is contained in:
parent
c91fbc82f8
commit
be086cf005
|
@ -8,6 +8,9 @@
|
|||
-->
|
||||
|
||||
## Upcoming release
|
||||
* For players:
|
||||
* Minor optimizations.
|
||||
|
||||
* For the web UI:
|
||||
* Fixed the mod count in the log parser metadata.
|
||||
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace StardewModdingAPI.Framework
|
||||
{
|
||||
/// <summary>A thread-safe command queue optimized for infrequent changes.</summary>
|
||||
internal class CommandQueue
|
||||
{
|
||||
/********
|
||||
** Fields
|
||||
********/
|
||||
/// <summary>The underlying list of queued commands to parse and execute.</summary>
|
||||
private readonly List<string> RawCommandQueue = new();
|
||||
|
||||
|
||||
/********
|
||||
** Public methods
|
||||
********/
|
||||
/// <summary>Add a command to the queue.</summary>
|
||||
/// <param name="command">The command to add.</param>
|
||||
public void Add(string command)
|
||||
{
|
||||
lock (this.RawCommandQueue)
|
||||
this.RawCommandQueue.Add(command);
|
||||
}
|
||||
|
||||
/// <summary>Remove and return all queued commands, if any.</summary>
|
||||
/// <param name="queued">The commands that were dequeued, in the order they were originally queued.</param>
|
||||
/// <returns>Returns whether any values were dequeued.</returns>
|
||||
[SuppressMessage("ReSharper", "InconsistentlySynchronizedField", Justification = "Deliberately check if it's empty before locking unnecessarily.")]
|
||||
public bool TryDequeue([NotNullWhen(true)] out string[]? queued)
|
||||
{
|
||||
if (this.RawCommandQueue.Count is 0)
|
||||
{
|
||||
queued = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
lock (this.RawCommandQueue)
|
||||
{
|
||||
queued = this.RawCommandQueue.ToArray();
|
||||
this.RawCommandQueue.Clear();
|
||||
return queued.Length > 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
@ -147,8 +146,7 @@ namespace StardewModdingAPI.Framework
|
|||
#endif
|
||||
|
||||
/// <summary>A list of queued commands to parse and execute.</summary>
|
||||
/// <remarks>This property must be thread-safe, since it's accessed from a separate console input thread.</remarks>
|
||||
private readonly ConcurrentQueue<string> RawCommandQueue = new();
|
||||
private readonly CommandQueue RawCommandQueue = new();
|
||||
|
||||
/// <summary>A list of commands to execute on each screen.</summary>
|
||||
private readonly PerScreen<List<QueuedCommand>> ScreenCommandQueue = new(() => new List<QueuedCommand>());
|
||||
|
@ -437,7 +435,7 @@ namespace StardewModdingAPI.Framework
|
|||
() => this.LogManager.RunConsoleInputLoop(
|
||||
commandManager: this.CommandManager,
|
||||
reloadTranslations: this.ReloadTranslations,
|
||||
handleInput: input => this.RawCommandQueue.Enqueue(input),
|
||||
handleInput: input => this.RawCommandQueue.Add(input),
|
||||
continueWhile: () => this.IsGameRunning && !this.CancellationToken.IsCancellationRequested
|
||||
)
|
||||
).Start();
|
||||
|
@ -525,29 +523,32 @@ namespace StardewModdingAPI.Framework
|
|||
/*********
|
||||
** Parse commands
|
||||
*********/
|
||||
while (this.RawCommandQueue.TryDequeue(out string? rawInput))
|
||||
if (this.RawCommandQueue.TryDequeue(out string[]? rawCommands))
|
||||
{
|
||||
// parse command
|
||||
string? name;
|
||||
string[]? args;
|
||||
Command? command;
|
||||
int screenId;
|
||||
try
|
||||
foreach (string rawInput in rawCommands)
|
||||
{
|
||||
if (!this.CommandManager.TryParse(rawInput, out name, out args, out command, out screenId))
|
||||
// parse command
|
||||
string? name;
|
||||
string[]? args;
|
||||
Command? command;
|
||||
int screenId;
|
||||
try
|
||||
{
|
||||
this.Monitor.Log("Unknown command; type 'help' for a list of available commands.", LogLevel.Error);
|
||||
if (!this.CommandManager.TryParse(rawInput, out name, out args, out command, out screenId))
|
||||
{
|
||||
this.Monitor.Log("Unknown command; type 'help' for a list of available commands.", LogLevel.Error);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.Monitor.Log($"Failed parsing that command:\n{ex.GetLogSummary()}", LogLevel.Error);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.Monitor.Log($"Failed parsing that command:\n{ex.GetLogSummary()}", LogLevel.Error);
|
||||
continue;
|
||||
}
|
||||
|
||||
// queue command for screen
|
||||
this.ScreenCommandQueue.GetValueForScreen(screenId).Add(new(command, name, args));
|
||||
// queue command for screen
|
||||
this.ScreenCommandQueue.GetValueForScreen(screenId).Add(new(command, name, args));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue