Context: In some games I'd imagine commands can be entered faster than they complete. For instance, a player might enter a movement command, and while the player is moving to that location, enter a command to cast a spell before the movement command has completed.
If that's true, it stands to reason that commands will likely need to queue into a central location from which another service can (asynchronously) pop those commands and service/execute them in the order they were received.
I'm trying to create a bug-free MVP of a system like this, and want to know if I'm on the right track.
Largely, I just don't know much about threads and I hear there are a bunch of gotchas (esp. with resource sharing), so just wanted to get some pointers on how to do this safely:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
|
#include <iostream>
#include <string>
#include <chrono>
#include <thread>
#include <queue>
#include <functional>
std::queue<std::string> commandQueue;
bool busy = false;
void executeCommand(std::string command)
{
std::this_thread::sleep_until(std::chrono::system_clock::now() + std::chrono::seconds(3)); // commands might "delay" the player.
std::cout << "Command " << command << " done." << std::endl;
}
void doNextCommand()
{
std::string cmd = commandQueue.front();
commandQueue.pop();
executeCommand(cmd);
if(!commandQueue.empty())
doNextCommand();
busy = false;
}
void serviceQueue()
{
if(busy) return;
busy = true;
// I have no idea what I'm doing here.I just think that I need to spin up a worker thread or make this
// async because it shouldn't block further command input
std::thread([](){ doNextCommand(); }).detach();
};
void commandQueueChanged()
{
serviceQueue();
}
int main()
{
while(true) {
std::cout << "Enter a command to fire" << std::endl;
std::string enterLine;
getline(std::cin, enterLine);
commandQueue.push(enterLine);
commandQueueChanged(); // Some event will fire that notifies the command servicer to start servicing commands.
};
return 0;
};
| |
The way I understand it, we have 2 threads accessing the queue. One adding and one servicing. That feels, to me, like it's going to cause a problem, but I'm not sure.
Is there a better way to do this, or a resource you've read that might help me build something a bit more robust?
This should be a running program: g++ main.cpp -std=c++20
Thank you!