I would like to have items added to a queue in one thread via in an asynchronous web request handler:
void handleRequest(item) {
toProcess.push_back(item);
}
There is a background thread that constantly processes these queue items as follows:
while(true) {
for(auto item : toProcess) { doSomething(item); }
toProcess.clear();
}
Clearly this isn't thread safe ... you might add an item to toProcess right when the for loop finishes and thus have it cleared out without being processed. What would be the best model to program something like this?
CodePudding user response:
I'm going to use std::atomic<T>::wait
which is a C 20
feature, there is a way to do it with condition variables too however, and they exist since C 11
.
Include <atomic>
and <mutex>
You will need a member atomic_bool.
std::atomic_bool RequestPassed = false;
and a member mutex
std::mutex RequestHandleMutex;
Your handleRequest function would then become
void handleRequest(item) {
std::lock_guard<std::mutex> lg(RequestHandleMutex)
toProcess.push_back(item);
RequestPassed.store(true);
RequestPassed.notify_all();
}
and your loop would be this
while(true) {
RequestPassed.wait(false);
std::lock_guard<std::mutex> lg(RequestHandleMutex)
/* handle latest item passed */
RequestPassed.store(false);
}
This way, the while thread waits instead of constantly iterating (saving cpu power and battery). If you then use handleRequest
, the atomic_bool gets notified to stop waiting, the request is handled (mutex is locked so no new requests can come while this happens), RequestPassed is reset to false, and the thread waits for the next request.