Browse Source

Add: check to prevent two or more scripts from running simultaneously

AnnulusGames 1 year ago
parent
commit
4bbfe9176a
2 changed files with 36 additions and 22 deletions
  1. 34 6
      src/Lua/LuaState.cs
  2. 2 16
      src/Lua/LuaStateExtensions.cs

+ 34 - 6
src/Lua/LuaState.cs

@@ -13,10 +13,12 @@ public sealed class LuaState
 
 
     LuaTable environment;
     LuaTable environment;
     internal UpValue EnvUpValue { get; }
     internal UpValue EnvUpValue { get; }
+    bool isRunning;
 
 
     internal LuaStack Stack => stack;
     internal LuaStack Stack => stack;
 
 
     public LuaTable Environment => environment;
     public LuaTable Environment => environment;
+    public bool IsRunning => Volatile.Read(ref isRunning);
 
 
     public static LuaState Create()
     public static LuaState Create()
     {
     {
@@ -29,6 +31,29 @@ public sealed class LuaState
         EnvUpValue = UpValue.Closed(environment);
         EnvUpValue = UpValue.Closed(environment);
     }
     }
 
 
+    public async ValueTask<int> RunAsync(Chunk chunk, Memory<LuaValue> buffer, CancellationToken cancellationToken = default)
+    {
+        ThrowIfRunning();
+
+        Volatile.Write(ref isRunning, true);
+        try
+        {
+            return await new Closure(this, chunk).InvokeAsync(new()
+            {
+                State = this,
+                ArgumentCount = 0,
+                StackPosition = 0,
+                SourcePosition = null,
+                RootChunkName = chunk.Name ?? DefaultChunkName,
+                ChunkName = chunk.Name ?? DefaultChunkName,
+            }, buffer, cancellationToken);
+        }
+        finally
+        {
+            Volatile.Write(ref isRunning, false);
+        }
+    }
+
     public ReadOnlySpan<LuaValue> GetStackValues()
     public ReadOnlySpan<LuaValue> GetStackValues()
     {
     {
         return stack.AsSpan();
         return stack.AsSpan();
@@ -36,15 +61,10 @@ public sealed class LuaState
 
 
     public void Push(LuaValue value)
     public void Push(LuaValue value)
     {
     {
+        ThrowIfRunning();
         stack.Push(value);
         stack.Push(value);
     }
     }
 
 
-    internal void Reset()
-    {
-        stack.Clear();
-        callStack.Clear();
-    }
-
     internal void PushCallStackFrame(CallStackFrame frame)
     internal void PushCallStackFrame(CallStackFrame frame)
     {
     {
         callStack.Push(frame);
         callStack.Push(frame);
@@ -106,4 +126,12 @@ public sealed class LuaState
             Console.WriteLine($"LuaStack [{i}]\t{span[i]}");
             Console.WriteLine($"LuaStack [{i}]\t{span[i]}");
         }
         }
     }
     }
+
+    void ThrowIfRunning()
+    {
+        if (Volatile.Read(ref isRunning))
+        {
+            throw new InvalidOperationException("the lua state is currently running");
+        }
+    }
 }
 }

+ 2 - 16
src/Lua/LuaStateExtensions.cs

@@ -1,5 +1,4 @@
 using System.Buffers;
 using System.Buffers;
-using Lua.Runtime;
 using Lua.CodeAnalysis.Compilation;
 using Lua.CodeAnalysis.Compilation;
 using Lua.CodeAnalysis.Syntax;
 using Lua.CodeAnalysis.Syntax;
 
 
@@ -7,24 +6,11 @@ namespace Lua;
 
 
 public static class LuaStateExtensions
 public static class LuaStateExtensions
 {
 {
-    public static ValueTask<int> RunAsync(this LuaState state, Chunk chunk, Memory<LuaValue> buffer, CancellationToken cancellationToken = default)
-    {
-        return new Closure(state, chunk).InvokeAsync(new()
-        {
-            State = state,
-            ArgumentCount = 0,
-            StackPosition = state.Stack.Count,
-            SourcePosition = null,
-            RootChunkName = chunk.Name ?? LuaState.DefaultChunkName,
-            ChunkName = chunk.Name ?? LuaState.DefaultChunkName,
-        }, buffer, cancellationToken);
-    }
-
     public static ValueTask<int> DoStringAsync(this LuaState state, string source, Memory<LuaValue> buffer, string? chunkName = null, CancellationToken cancellationToken = default)
     public static ValueTask<int> DoStringAsync(this LuaState state, string source, Memory<LuaValue> buffer, string? chunkName = null, CancellationToken cancellationToken = default)
     {
     {
         var syntaxTree = LuaSyntaxTree.Parse(source);
         var syntaxTree = LuaSyntaxTree.Parse(source);
         var chunk = LuaCompiler.Default.Compile(syntaxTree, chunkName);
         var chunk = LuaCompiler.Default.Compile(syntaxTree, chunkName);
-        return RunAsync(state, chunk, buffer, cancellationToken);
+        return state.RunAsync(chunk, buffer, cancellationToken);
     }
     }
 
 
     public static async ValueTask<LuaValue[]> DoStringAsync(this LuaState state, string source, string? chunkName = null, CancellationToken cancellationToken = default)
     public static async ValueTask<LuaValue[]> DoStringAsync(this LuaState state, string source, string? chunkName = null, CancellationToken cancellationToken = default)
@@ -47,7 +33,7 @@ public static class LuaStateExtensions
         var fileName = Path.GetFileName(path);
         var fileName = Path.GetFileName(path);
         var syntaxTree = LuaSyntaxTree.Parse(text, fileName);
         var syntaxTree = LuaSyntaxTree.Parse(text, fileName);
         var chunk = LuaCompiler.Default.Compile(syntaxTree, fileName);
         var chunk = LuaCompiler.Default.Compile(syntaxTree, fileName);
-        return await RunAsync(state, chunk, buffer, cancellationToken);
+        return await state.RunAsync(chunk, buffer, cancellationToken);
     }
     }
 
 
     public static async ValueTask<LuaValue[]> DoFileAsync(this LuaState state, string path, CancellationToken cancellationToken = default)
     public static async ValueTask<LuaValue[]> DoFileAsync(this LuaState state, string path, CancellationToken cancellationToken = default)