The following code has concurrency issues. Here inDegVec is a global int *, and getGUID() and getTime() are innocuous accessors for POD variables.
void operator () ( GNode& src,
tbb::parallel_do_feeder<GNode>& feed_it )
const
{
std::list<GNode> addNodes;
// some thread-safe code that populates addNodes
while (!addNodes.empty()) {
feed_it.add(addNodes.front());
addNodes.pop_front();
}
if (inDegVec[srcAVI->getUID()] == 0) {
// srcAVI is still the minimum among its neighbors
if (srcAVI->getTime() < colTime) {
//lwl.push (src);
//tbb::mutex::scoped_lock lock(histMutex);
assert(addNodes.empty());
feed_it.add(src);
}
}
};
If I wrap the while/if blocks in a mutex, the code works. But why is this necessary? Is parallel_do_feeder::add() not thread-safe? The example code I’ve seen (such as http://llpanorama.wordpress.com/2008/03/09/parallel_do-parallel-done/) use no synchronization, suggesting that it is… and I don’t see a discussion of parallel_do_feeder’s thread safety in the TBB manual.
Yes,
parallel_do_feederis thread safe.Is the copy constructor of
GNodethread safe? The instance ofGNodepassed toparallel_do_feeder::add()is copied into a task that will process it (possibly in another thread).