From c0665e7c613cee6994741a2ccac9e804e3601f60 Mon Sep 17 00:00:00 2001 From: JAJames Date: Sat, 13 Feb 2016 06:49:21 -0500 Subject: [PATCH] Learned how to use a mutex. Updated Jupiter. --- Bot/Main.cpp | 57 ++++++++++++++++++++++++++-------- Jupiter | 2 +- Release/Bot.lib | Bin 24762 -> 24762 bytes Release/Plugins/RenX.Core.lib | Bin 192518 -> 192518 bytes 4 files changed, 45 insertions(+), 14 deletions(-) diff --git a/Bot/Main.cpp b/Bot/Main.cpp index d2f2505..465f246 100644 --- a/Bot/Main.cpp +++ b/Bot/Main.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include "Jupiter/Functions.h" #include "Jupiter/INIFile.h" #include "Jupiter/Queue.h" @@ -34,7 +35,16 @@ using namespace Jupiter::literals; -Jupiter::Queue inputQueue; +#define INPUT_BUFFER_SIZE 2048 + +struct ConsoleInput +{ + Jupiter::String input; + std::mutex input_mutex; + bool awaiting_processing = false; + + ConsoleInput() : input(INPUT_BUFFER_SIZE) {} +} console_input; void onTerminate() { @@ -50,12 +60,27 @@ void onExit() void inputLoop() { - char input[2048]; + char input[INPUT_BUFFER_SIZE]; + size_t input_length; while (ftell(stdin) != -1) // This can be expanded later to check for EBADF specifically. { fgets(input, sizeof(input), stdin); - input[strcspn(input, "\r\n")] = 0; - inputQueue.enqueue(input); + input_length = strcspn(input, "\r\n"); + + check_input_processing: + + console_input.input_mutex.lock(); + if (console_input.awaiting_processing == false) + { + console_input.input.set(input, input_length); + console_input.awaiting_processing = true; + console_input.input_mutex.unlock(); + } + else // User input received before previous input was processed. + { + std::this_thread::sleep_for((std::chrono::seconds(1))); + goto check_input_processing; + } } } @@ -64,6 +89,7 @@ int main(int argc, const char **args) atexit(onExit); std::set_terminate(onTerminate); std::thread inputThread(inputLoop); + Jupiter::ReferenceString command; srand(static_cast(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count())); puts(Jupiter::copyright); @@ -146,16 +172,21 @@ int main(int argc, const char **args) ++index; Jupiter_checkTimers(); serverManager->think(); - Jupiter::ReferenceString input = (const char *)inputQueue.dequeue(); - if (input.isNotEmpty()) + + if (console_input.input_mutex.try_lock()) { - Jupiter::ReferenceString command = input.getWord(0, WHITESPACE); - - ConsoleCommand *cmd = getConsoleCommand(command); - if (cmd != nullptr) - cmd->trigger(input.gotoWord(1, WHITESPACE)); - else - printf("Error: Command \"%.*s\" not found." ENDL, command.size(), command.ptr()); + if (console_input.awaiting_processing) + { + console_input.awaiting_processing = false; + command = console_input.input.getWord(0, WHITESPACE); + + ConsoleCommand *cmd = getConsoleCommand(command); + if (cmd != nullptr) + cmd->trigger(console_input.input.gotoWord(1, WHITESPACE)); + else + printf("Error: Command \"%.*s\" not found." ENDL, command.size(), command.ptr()); + } + console_input.input_mutex.unlock(); } std::this_thread::sleep_for((std::chrono::milliseconds(1))); } diff --git a/Jupiter b/Jupiter index 1df5bee..6b88571 160000 --- a/Jupiter +++ b/Jupiter @@ -1 +1 @@ -Subproject commit 1df5bee1d49817471d9151b019dd244a610069eb +Subproject commit 6b8857178ab821141510bd1cf942182840127ac5 diff --git a/Release/Bot.lib b/Release/Bot.lib index 0df49a80a776bd3c579b8bee1212a54a42fa139f..20e988ff3bd41adcfc2f1f441c8531a05f73b03c 100644 GIT binary patch delta 1981 zcmZuxJ4{ni7;bq83bB|LbgQX*agCPa7(FFJ12G zzSsk^S!vCZ;{WGE_3JAQ^8(;A8hZNrO!zl>B&aRbG}dpfC;Pr?nM&Sggp5UBN( z6vfNBQJY=Ge{C~VQ{7ggTSk7M)fr&l)}|sob0evVkjjx{ghf|nQT9bUx_@aO-~u5D z{wR2zV~pYY*g4tJvLnGT=Qv_#oiT=);}YzRqwcEn4#UZmV8(-Z&J|>M-Y3Df3-Nu| zpbB>kBAy&ncR}p#QPSP_r45jAivyP@Ap5nr)v=^GGXBclFXS>piKkY^k9)2#T=6VV zvWqmchU7Xp)IoaL$T-x0!Dsmp&qZVRhA`Ls&xv$c=^d7j6zeolDsM6w6>GnJbgO4QdoS9sP&NI-?aru@qAloF;mJ}eMxam z8mk+_hTOY4%kvBP>9POg+X7yA(r%3xJ!$gE=7_I;;;Xu54CZ3If7I9GYv?^hI99@0 zJL4@HoOs%Qb}Ewq9yEf{n&Wg)~w2TgEM#N>~Y zA(p|(2oe@U;)9XF5JwUTlQD4-2jgI(o^$`(bI!HWiSK^@_kaKEY;I{cx3rIqRXx`3 z-k!d0n9WM-))fE05NX<2HO>n_z@YEx>oeis)RC~ZT(iFTdL!BQRm)Tg0Rv>Lx^ns< zZ!J@Qcx1y5E4CBj2MKoVdKv-W>|Q}h0=q+BL-5pTjYgx@RKWLBP4LiD16ikD#Vf|| z_Ls!Vx^ah7#eeD0*HYa!qFX_JpsmxxzN1}5dNPQlW1D?jjnNq>k{W>M=P!|hPfvYJLgU?%rYv$-URBdxo6fsJOSCSbx<8knj_;c25mwv1C)6iWc;}IGQ$l{TF>!4)I(xc5euC%@6q*U%_R~E~42;G+&w8p~c5FO(6-o z(ioff@fj4zY(D!C|K&?DP3oaI%Y|WKmID4mg&QF1$9k{(#d>j`AN@h5J)1==7T{PR zfY^rs&!r0@<_OLRu@bxs;xcxUT3hHc9@ClNcaRUu6vDtrD9ZwAL1f7CK=woGrrN`Z z$HUx^*zBFKy4k%Em{v~BSYRjF2JSHz zV<%SL?F){nzng7=U5TD*$hBZOlo zob|K5lEI0m?MVx#omMt7%{Q-jdhrb3bjxTHY-Z}^%h<`>V|CK}`AN(lCi&eY|3OD9 ztWK6pOO9>L^1c`IEN6KhI-|-Q_S2YCKi3Ni{xs)i`Nf5-o8sE^lINyS=fRZuFFW;W AZ2$lO diff --git a/Release/Plugins/RenX.Core.lib b/Release/Plugins/RenX.Core.lib index e24239615f0460e72e123bb69016a966792c3b1f..02676ea0ee5f9970462fe890295663fe7770ad52 100644 GIT binary patch delta 13403 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 U#$!gE7f*sjSmEb!sZK}#KTNTTZ2$lO delta 13403 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