I have the following problem.
I have two classes, in this case A and B, which both own a concurrent_queue
. The assumption here is that concurrent_queue is a thread-safe queue, with a blocking push() function. When an object is enqueued in B, it accesses the singleton A and it is queued up in A as well. This has the effect that a whole bunch of B's have little queues with their own objects, and one large queue in A that contains them all. Each instance of B could live in a separate thread.
What I am encountering is that frequently a thread will get pre-empted between the two lines of code in B::foo(), meaning A::mQueue contains the object, but B::mQueue does not yet contain the object.
What I am wondering is how I can ensure that when B::foo() is called that the object is either pushed onto both queues or neither queue. It seems to me that I would have to have a mutex in A that B can get a hold of, and lock A's mutex in B::foo().
Does anyone have any suggestions how I could accomplish this, or how I could restructure my code to accomplish this? I am using the boost::threading library.
Class A
{
public:
A& instance(){/* return singleton */}
void addToQueue(SomeObject const& obj)
{
mQueue.push(obj);
}
private:
concurrent_queue<SomeObject> mQueue;
};
Class B
{
public:
void foo()
{
SomeObject obj;
//I would like to guarantee that obj is either present in both queues or neither queue
A::instance().addToQueue(obj);
mQueue.push(obj);
}
private:
concurrent_queue<SomeObject> mQueue;
};
In my actual implementation, it is not the same object that gets queued up in A and B, rather the A queues up structs that contain pointers to B's, which let me dequeue everything in A and dequeue from all the B's in the same order that they were queued up in, but this should be irrelevant to the question.