Browse Source

Merge branch 'ansi-parser' into ansi-parser-net-driver

tznind 9 months ago
parent
commit
d7183f6364
1 changed files with 39 additions and 13 deletions
  1. 39 13
      Terminal.Gui/ConsoleDrivers/AnsiResponseParser/AnsiResponseParser.cs

+ 39 - 13
Terminal.Gui/ConsoleDrivers/AnsiResponseParser/AnsiResponseParser.cs

@@ -5,7 +5,9 @@ namespace Terminal.Gui;
 
 internal abstract class AnsiResponseParserBase : IAnsiResponseParser
 {
-    object lockExpectedResponses = new object();
+    protected object lockExpectedResponses = new object();
+
+    protected object lockState = new object ();
     /// <summary>
     /// Responses we are expecting to come in.
     /// </summary>
@@ -85,6 +87,19 @@ internal abstract class AnsiResponseParserBase : IAnsiResponseParser
         Action<object> appendOutput,
         int inputLength
     )
+    {
+        lock (lockState)
+        {
+            ProcessInputBaseImpl (getCharAtIndex, getObjectAtIndex, appendOutput, inputLength);
+        }
+    }
+
+    private void ProcessInputBaseImpl (
+        Func<int, char> getCharAtIndex,
+        Func<int, object> getObjectAtIndex,
+        Action<object> appendOutput,
+        int inputLength
+    )
     {
         var index = 0; // Tracks position in the input string
 
@@ -334,12 +349,17 @@ internal class AnsiResponseParser<T> : AnsiResponseParserBase
 
     public IEnumerable<Tuple<char, T>> Release ()
     {
-        foreach (Tuple<char, T> h in HeldToEnumerable())
+        // Lock in case Release is called from different Thread from parse
+        lock (lockState)
         {
-            yield return h;
+            foreach (Tuple<char, T> h in HeldToEnumerable())
+            {
+                yield return h;
+            }
+
+            ResetState ();
         }
 
-        ResetState ();
     }
 
     private IEnumerable<Tuple<char, T>> HeldToEnumerable ()
@@ -356,13 +376,16 @@ internal class AnsiResponseParser<T> : AnsiResponseParserBase
     /// <param name="persistent"></param>
     public void ExpectResponseT (string terminator, Action<IEnumerable<Tuple<char,T>>> response, bool persistent)
     {
-        if (persistent)
-        {
-            persistentExpectations.Add (new (terminator, (h) => response.Invoke (HeldToEnumerable ())));
-        }
-        else
+        lock (lockExpectedResponses)
         {
-            expectedResponses.Add (new (terminator, (h) => response.Invoke (HeldToEnumerable ())));
+            if (persistent)
+            {
+                persistentExpectations.Add (new (terminator, (h) => response.Invoke (HeldToEnumerable ())));
+            }
+            else
+            {
+                expectedResponses.Add (new (terminator, (h) => response.Invoke (HeldToEnumerable ())));
+            }
         }
     }
 
@@ -405,10 +428,13 @@ internal class AnsiResponseParser : AnsiResponseParserBase
 
     public string Release ()
     {
-        var output = heldContent.HeldToString ();
-        ResetState ();
+        lock (lockState)
+        {
+            var output = heldContent.HeldToString ();
+            ResetState ();
 
-        return output;
+            return output;
+        }
     }
 
     /// <inheritdoc />