Skip to content

Commit 557903d

Browse files
committed
Async input queues for Instance.
1 parent 7aa7dea commit 557903d

File tree

1 file changed

+56
-66
lines changed

1 file changed

+56
-66
lines changed

Guncho.Core/Instance.cs

+56-66
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
using System.Text.RegularExpressions;
99
using System.Threading.Tasks;
1010
using Nito.AsyncEx;
11+
using System.Collections.Concurrent;
12+
using System.Diagnostics.Contracts;
1113

1214
namespace Guncho
1315
{
@@ -806,10 +808,9 @@ private bool AllowSetPlayerAttribute(string name, string value)
806808
private class RealmIO
807809
{
808810
private readonly Instance instance;
809-
private readonly Queue<string> inputQueue = new Queue<string>();
810-
private readonly Queue<Transaction> transQueue = new Queue<Transaction>();
811-
private readonly Queue<string> specialResponses = new Queue<string>();
812-
private readonly AutoResetEvent inputReady = new AutoResetEvent(false);
811+
private readonly AsyncProducerConsumerQueue<object> inputQueue = new AsyncProducerConsumerQueue<object>(); // string
812+
private readonly AsyncProducerConsumerQueue<object> transQueue = new AsyncProducerConsumerQueue<object>(); // Transaction
813+
private readonly ConcurrentQueue<string> specialResponses = new ConcurrentQueue<string>();
813814
private Transaction curTrans;
814815

815816
public RealmIO(Instance instance)
@@ -819,32 +820,21 @@ public RealmIO(Instance instance)
819820

820821
public void QueueInput(string line)
821822
{
822-
lock (inputQueue)
823-
{
824-
inputQueue.Enqueue(line);
825-
826-
if (inputQueue.Count == 1)
827-
inputReady.Set();
828-
}
823+
inputQueue.Enqueue(line);
829824
}
830825

831826
public void QueueTransaction(Transaction trans)
832827
{
833-
lock (transQueue)
834-
{
835-
transQueue.Enqueue(trans);
836-
837-
if (transQueue.Count == 1)
838-
inputReady.Set();
839-
}
828+
transQueue.Enqueue(trans);
840829
}
841830

842831
private static Regex chatRegex = new Regex(@"^(-?\d+):\$(say|emote) (?:\>([^ ]*) )?(.*)$");
843832

844833
private async Task<string> GetInputLineAsync()
845834
{
846-
if (specialResponses.Count > 0)
847-
return specialResponses.Dequeue();
835+
string specialResponse;
836+
if (specialResponses.TryDequeue(out specialResponse))
837+
return specialResponse;
848838

849839
instance.DisableWatchdog();
850840

@@ -866,65 +856,65 @@ private async Task<string> GetInputLineAsync()
866856
curTrans = null;
867857
}
868858

859+
var queues = new AsyncProducerConsumerQueue<object>[] { transQueue, inputQueue };
860+
869861
do
870862
{
871-
// is there a transaction waiting?
872-
lock (transQueue)
863+
// wait for a transaction or a line of player input
864+
var dqResult = await queues.TryDequeueFromAnyAsync();
865+
866+
if (!dqResult.Success)
867+
throw new InvalidOperationException("failed to get input");
868+
869+
if (dqResult.Queue == transQueue)
873870
{
874-
if (transQueue.Count > 0)
875-
{
876-
curTrans = transQueue.Dequeue();
877-
instance.logger.LogMessage(LogLevel.Spam,
878-
"Transaction in {0}: {1}",
879-
instance.name, curTrans.Query);
880-
return curTrans.Query;
881-
}
871+
// got a transaction
872+
curTrans = (Transaction)dqResult.Item;
873+
instance.logger.LogMessage(LogLevel.Spam,
874+
"Transaction in {0}: {1}",
875+
instance.name, curTrans.Query);
876+
return curTrans.Query;
882877
}
883-
884-
// is there a line of player input waiting?
885-
lock (inputQueue)
878+
else
886879
{
887-
if (inputQueue.Count > 0)
888-
{
889-
string line = inputQueue.Dequeue();
890-
instance.logger.LogMessage(LogLevel.Spam,
891-
"Processing in {0}: {1}",
892-
instance.name, line);
880+
Contract.Assert(dqResult.Queue == inputQueue);
881+
882+
// got a line of player input
883+
string line = (string)dqResult.Item;
884+
instance.logger.LogMessage(LogLevel.Spam,
885+
"Processing in {0}: {1}",
886+
instance.name, line);
893887

894-
if (!instance.rawMode)
888+
if (!instance.rawMode)
889+
{
890+
if (line.StartsWith("$silent "))
895891
{
896-
if (line.StartsWith("$silent "))
897-
{
898-
// set up a fake transaction so the output will be hidden
899-
// and the next line's output substituted instead
900-
line = line.Substring(8);
901-
curTrans = new DisambigHelper(instance, line);
902-
}
903-
else
892+
// set up a fake transaction so the output will be hidden
893+
// and the next line's output substituted instead
894+
line = line.Substring(8);
895+
curTrans = new DisambigHelper(instance, line);
896+
}
897+
else
898+
{
899+
Match m = chatRegex.Match(line);
900+
if (m.Success)
904901
{
905-
Match m = chatRegex.Match(line);
906-
if (m.Success)
907-
{
908-
string id = m.Groups[1].Value;
909-
string type = m.Groups[2].Value;
910-
string target = m.Groups[3].Value;
911-
string msg = m.Groups[4].Value;
912-
instance.chatTargetRegister = target;
913-
instance.chatMsgRegister = msg;
914-
line = id + ":$" + type;
915-
}
902+
string id = m.Groups[1].Value;
903+
string type = m.Groups[2].Value;
904+
string target = m.Groups[3].Value;
905+
string msg = m.Groups[4].Value;
906+
instance.chatTargetRegister = target;
907+
instance.chatMsgRegister = msg;
908+
line = id + ":$" + type;
916909
}
917910
}
911+
}
918912

919-
if (line.Length > MAX_LINE_LENGTH)
920-
line = line.Substring(0, MAX_LINE_LENGTH);
913+
if (line.Length > MAX_LINE_LENGTH)
914+
line = line.Substring(0, MAX_LINE_LENGTH);
921915

922-
return line;
923-
}
916+
return line;
924917
}
925-
926-
// wait for input and then continue the loop
927-
inputReady.WaitOne();
928918
} while (true);
929919
}
930920
finally

0 commit comments

Comments
 (0)