A common way to handle message queues is to actually have two queues, one where the sender adds its message, and one for the reply. Then instead of using simple strings in the queue, you have a structure which contains the data (the string in your case) and the queue where to add the replies and maybe some kind of identifier to know what message the reply is for.
It's some extra memory overhead as the number of queues increases, but considering this scheme was used on computers in the mid 1980's with only 512 kb RAM (or even less) one can conclude that the overhead is not very big.
As for the implementation, you could create a simple class wrapping most of the functionality, even making it a templated class if you want different queues to be able to receive different data.
Maybe something similar to this:
template<typename Td>
class message_queue
{
public:
static const message_queue<Td> none{};
// Post a message to the queue, with an optional reply queue
void post(const Td& data, message_queue<Td>& reply_queue = none);
// Get the first message from the queue
// The second member of the pair is an optional message queue
// where the reply is posted, it's `none` if no reply needed
std::pair<Td, message_queue<Td>> get();
// Wait for a message to arrive in the queue
void wait() const;
private:
// The actual message queue
std::queue<std::pair<Td, message_queue<Td>> queue;
}
The class above can be used something like this:
message_queue<std::string> sql_queue;
// ...
message_queue<std::string> reply_queue;
sql_queue.post("SELECT * FROM some_table", reply_queue);
reply_queue.wait();
std::string data = reply_queue.get().first;
sqlite3_open_v2(Path.c_str(), &DatabaseConnection, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX, NULL);and I dont need to check if I already insert something? For the other threads I would use the SQLITE_OPEN_READONLY and FULLÖMUTEX flag?