Add try-catch and locking to framework manager.

This commit is contained in:
Ottermandias 2022-07-30 18:39:39 +02:00
parent ff5e72e979
commit 2ca90f2518

View file

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Dalamud.Game; using Dalamud.Game;
using Dalamud.Logging;
namespace Penumbra.Util; namespace Penumbra.Util;
@ -19,57 +20,81 @@ public class FrameworkManager : IDisposable
// One action per frame will be executed. // One action per frame will be executed.
// On dispose, any remaining actions will be executed. // On dispose, any remaining actions will be executed.
public void RegisterDelayed( string tag, Action action ) public void RegisterDelayed( string tag, Action action )
=> _delayed[ tag ] = action; {
lock( _delayed )
{
_delayed[ tag ] = action;
}
}
// Register an action that should be executed on the next frame. // Register an action that should be executed on the next frame.
// All of those actions will be executed in the next frame. // All of those actions will be executed in the next frame.
// If there are more than one, they will be launched in separated tasks, but waited for. // If there are more than one, they will be launched in separated tasks, but waited for.
public void RegisterImportant( string tag, Action action ) public void RegisterImportant( string tag, Action action )
=> _important[ tag ] = action; {
lock( _important )
{
_important[ tag ] = action;
}
}
public void Dispose() public void Dispose()
{ {
Dalamud.Framework.Update -= OnUpdate; Dalamud.Framework.Update -= OnUpdate;
HandleAll( _delayed ); foreach( var (_, action) in _delayed )
{
action();
}
_delayed.Clear();
} }
private void OnUpdate( Framework _ ) private void OnUpdate( Framework _ )
{ {
HandleOne(); try
HandleAllTasks( _important );
}
private void HandleOne()
{
if( _delayed.Count > 0 )
{ {
var (key, action) = _delayed.First(); HandleOne( _delayed );
action(); HandleAllTasks( _important );
_delayed.Remove( key ); }
catch( Exception e )
{
PluginLog.Error( $"Problem saving data:\n{e}" );
} }
} }
private static void HandleAll( IDictionary< string, Action > dict ) private static void HandleOne( IDictionary< string, Action > dict )
{ {
foreach( var (_, action) in dict ) if( dict.Count == 0 )
{ {
action(); return;
} }
dict.Clear(); Action action;
lock( dict )
{
( var key, action ) = dict.First();
dict.Remove( key );
}
action();
} }
private static void HandleAllTasks( IDictionary< string, Action > dict ) private static void HandleAllTasks( IDictionary< string, Action > dict )
{ {
if( dict.Count < 2 ) if( dict.Count < 2 )
{ {
HandleAll( dict ); HandleOne( dict );
} }
else else
{ {
var tasks = dict.Values.Select( Task.Run ).ToArray(); Task[] tasks;
lock( dict )
{
tasks = dict.Values.Select( Task.Run ).ToArray();
dict.Clear();
}
Task.WaitAll( tasks ); Task.WaitAll( tasks );
dict.Clear();
} }
} }
} }