问题
I have created a thread safe queue (see code). The class seems to work but now I want to make the combination front() plus pop() thread safe in such a way that a thread first gets the element and then for sure removes the same element. I can come up with some solutions but they are not elegant for the user side or the strong exception safety guarantee will be lost.
The first solution is that the user simply has to lock the ThreadQueueu than call front() and pop() and unlock the ThreadQueue. However, the whole idea of the class is that the user has not to mind about the thread safety.
The second solution is to lock the queue inside the overloaded function front() and only unlock it in pop(). However, in this case the user is not allowed to only call front() or pop(), not that user friendly..
The third option I came up with is to create a public function in the class (frontPop) which returns the front element and removes it. However in this case the exception safety is gone.
What is the solution which is both user friendly (elegant) and maintain the exception safety?
class ThreadQueue: private std::queue<std::string>
{
mutable std::mutex d_mutex;
public:
void pop()
{
lock_guard<mutex> lock(d_mutex);
pop();
}
std::string &front()
{
lock_guard<mutex> lock(d_mutex);
return front();
}
// All other functions
private:
};
回答1:
The usual solution is to provide a combined front & pop that accepts a reference into which to store the popped value, and returns a bool
that is true
if a value was popped:
bool pop(std::string& t) {
lock_guard<mutex> lock(d_mutex);
if (std::queue<std::string>::empty()) {
return false;
}
t = std::move(std::queue<std::string>::front());
std::queue<std::string>::pop();
return true;
}
Any exceptions thrown by the move assignment happen before the queue is modified, maintaining the exception guarantee provided by the value type's move assignment operator.
来源:https://stackoverflow.com/questions/28417822/thread-safe-queue-with-front-pop