There is an online game server to which I want to fasten simple statistics, I decided to use sqlite3.
The problem is that making requests synchronously on the server in the main thread is not allowed, and asynchronous API if I am not mistaken, sqlite does not have.
I assume that you need to create a thread, and in it it’s a queue to send requests to the stream from the main server thread that it will execute while respecting the queue and call the callback functions.
Is this being done? If so, how can this be implemented?
I didn’t write to multi-threaded applications and can only do the simplest operations with threads, but I don’t have a clue how to “transmit” something to the stream.
- Clarify the question. Is it about "transferring something to the stream", or about organizing joint access to shared resources? - PinkTux
- Probably the first, I need to pass a request to the sql stream, a small portion of the data and a callback function to execute it after the request is completed - Vitaly Karpenko
- It seems that you are trying to implement the classic algorithm Consumer-Producer. - KoVadim 4:05 pm
|
2 answers
In C ++ 11, you can make asynchronous calls using std::async . Here is a small example. You can substitute and Lyabda instead of the usual function. Everything is implemented quite simply, but the only negative is a separate thread for each challenge. Although, if database queries are not heavy, then it is likely that many threads will not be created.
- There are not many requests for change. But enough, therefore, does not fit - Vitaly Karpenko
- @Vitaliy The question is not in the number of requests, but in their "gravity". There may be a lot of requests, but if they are executed quickly, then by the time the next request starts (the thread is created), the previous request may already be executed (and the thread will be closed). If you make one separate thread, in which you will put these requests for execution, you will get almost the same thing that you are trying to avoid. In this second thread, there will be exactly the same problems due to one “heavy” query, as in the main thread. - Max ZS
- Queries are simple (regular update). I can't allow myself ideologically to create a stream for each request because the rest of the code is written as productively as possible, and if I add in there some not very optimal code then the server will turn into a tortoise - Julia Karpenko
|
A few hours of studying STL and C ++ and I was able to implement it;)
#include <condition_variable> #include <mutex> #include <thread> #include <iostream> #include <queue> #include <chrono> typedef struct { const char *sql; // etc... } query_t; int main() { std::queue<query_t> requests; std::mutex mtx; std::mutex notify; notify.lock(); std::thread db_async_worker([&]() { std::queue<query_t> temp; while (true) { mtx.lock(); if (!requests.empty()) { temp = requests; while (!requests.empty()) requests.pop(); } mtx.unlock(); while (!temp.empty()) { std::cout << "execing db query " << temp.front().sql << '\n'; // sqlite3_exec() // ... std::this_thread::sleep_for(std::chrono::seconds(3)); // simulate slow query temp.pop(); } notify.lock(); } }); while (true) { std::this_thread::sleep_for(std::chrono::seconds(1)); std::cout << "add sql query to db queue" << '\n'; mtx.lock(); requests.push({"UPDATE INTO ..."}); mtx.unlock(); notify.unlock(); } } |