Fix concurrency in ConsoleIO

Fix concurrency issues by using proper locks
This commit is contained in:
ORelio 2015-05-10 18:57:33 +02:00
parent 72498a6756
commit 3376247826

View file

@ -14,16 +14,30 @@ namespace MinecraftClient
public static class ConsoleIO public static class ConsoleIO
{ {
public static void Reset() { if (reading) { ClearLineAndBuffer(); reading = false; Console.Write("\b \b"); } }
public static void SetAutoCompleteEngine(IAutoComplete engine) { autocomplete_engine = engine; }
public static bool basicIO = false; public static bool basicIO = false;
private static IAutoComplete autocomplete_engine; private static IAutoComplete autocomplete_engine;
private static LinkedList<string> previous = new LinkedList<string>(); private static LinkedList<string> previous = new LinkedList<string>();
private static string buffer = ""; private static string buffer = "";
private static string buffer2 = ""; private static string buffer2 = "";
private static bool reading = false; private static bool reading = false;
private static bool reading_lock = false; private static object io_lock = new object();
private static bool writing_lock = false;
/// <summary>
/// Reset the IO mechanism & clear all buffers
/// </summary>
public static void Reset()
{
lock (io_lock)
{
if (reading)
{
ClearLineAndBuffer();
reading = false;
Console.Write("\b \b");
}
}
}
/// <summary> /// <summary>
/// Read a password from the standard input /// Read a password from the standard input
@ -82,16 +96,20 @@ namespace MinecraftClient
{ {
if (basicIO) { return Console.ReadLine(); } if (basicIO) { return Console.ReadLine(); }
ConsoleKeyInfo k = new ConsoleKeyInfo(); ConsoleKeyInfo k = new ConsoleKeyInfo();
Console.Write('>');
reading = true; lock (io_lock)
buffer = ""; {
buffer2 = ""; Console.Write('>');
reading = true;
buffer = "";
buffer2 = "";
}
while (k.Key != ConsoleKey.Enter) while (k.Key != ConsoleKey.Enter)
{ {
k = Console.ReadKey(true); k = Console.ReadKey(true);
while (writing_lock) { } lock (io_lock)
reading_lock = true; {
if (k.Key == ConsoleKey.V && k.Modifiers == ConsoleModifiers.Control) if (k.Key == ConsoleKey.V && k.Modifiers == ConsoleModifiers.Control)
{ {
string clip = ReadClipboard(); string clip = ReadClipboard();
@ -173,13 +191,16 @@ namespace MinecraftClient
AddChar(k.KeyChar); AddChar(k.KeyChar);
break; break;
} }
}
} }
reading_lock = false;
} }
while (writing_lock) { }
reading = false; lock (io_lock)
previous.AddLast(buffer + buffer2); {
return buffer + buffer2; reading = false;
previous.AddLast(buffer + buffer2);
return buffer + buffer2;
}
} }
/// <summary> /// <summary>
@ -188,9 +209,10 @@ namespace MinecraftClient
public static void Write(string text) public static void Write(string text)
{ {
if (basicIO) { Console.Write(text); return; } if (!basicIO)
while (reading_lock) { } {
writing_lock = true; lock (io_lock)
{
if (reading) if (reading)
{ {
try try
@ -221,12 +243,13 @@ namespace MinecraftClient
{ {
//Console resized: Try again //Console resized: Try again
Console.Write('\n'); Console.Write('\n');
writing_lock = false;
Write(text); Write(text);
} }
} }
else Console.Write(text); else Console.Write(text);
writing_lock = false; }
}
else Console.Write(text);
} }
/// <summary> /// <summary>
@ -289,7 +312,7 @@ namespace MinecraftClient
case 'd': Console.ForegroundColor = ConsoleColor.Magenta; break; case 'd': Console.ForegroundColor = ConsoleColor.Magenta; break;
case 'e': Console.ForegroundColor = ConsoleColor.Yellow; break; case 'e': Console.ForegroundColor = ConsoleColor.Yellow; break;
case 'f': Console.ForegroundColor = ConsoleColor.White; break; case 'f': Console.ForegroundColor = ConsoleColor.White; break;
case 'r': Console.ForegroundColor = ConsoleColor.White; break; case 'r': Console.ForegroundColor = ConsoleColor.Gray; break;
} }
if (subs[i].Length > 1) if (subs[i].Length > 1)
@ -387,6 +410,18 @@ namespace MinecraftClient
return clipdata; return clipdata;
} }
#endregion #endregion
#region AutoComplete API
/// <summary>
/// Set an auto-completion engine for TAB autocompletion
/// </summary>
/// <param name="engine">Engine implementing the IAutoComplete interface</param>
public static void SetAutoCompleteEngine(IAutoComplete engine)
{
autocomplete_engine = engine;
}
#endregion
} }
/// <summary> /// <summary>