Dr. Dobb's Journal - July 2008 - (Page 44) Core Technology LOCK-FREE QUEUES }; Figure 1: Adding an empty T() element in the constructor of the LockFreeQueue . Figure 2: The Ping-Pong test. Consume() may fail to read an element (and return false). Unlike traditional lockbased queues, this queue works fast when the queue is not empty, but needs an external locking or polling method to wait for data. Sometimes you want to wait if there is no element available in the queue, and avoid returning false. A naive approach to waiting is: T Consume() { T tmp; while (!Consume(tmp)) ; return tmp; } Considering how simple this code is, you might wonder how can it be threadsafe. The magic is due to design, not implementation. Take a look at the implementation of the Produce() and Consume() methods. The Produce() method looks like this: void Produce(const T& t) { list.push_back(t); iTail = list.end(); list.erase(list.begin(), iHead); } To understand how this works, mentally separate the data from LockFreeQueue into two groups: • The list and the iTail iterator, modified by the Produce() method (Producer thread). • The iHead iterator, modified by the Consume() method (Consumer thread). Produce() is the only method that changes the list (adding new elements and erasing the consumed elements), and it is essential that only one thread ever calls Produce()—it’s the Producer thread! The iterator (iTail) (only manipulated by the Producer thread) changes it only after a new element is added to the list. This way, when the Consumer thread is reading the iTail element, the new added element is ready to be used. The Consume() method tries to read all the elements between iHead and iTail (excluding both ends). bool Consume(T& t) { typename TList::iterator iNext = iHead; ++iNext; if (iNext != iTail) { iHead = iNext; t = *iHead; return true; } return false; } This method reads the elements, but doesn’t remove them from the list. Nor does it access the list directly, but through the iterators. They are guaranteed to be valid after std::list is modified, so no matter what the Producer thread does to the list, you are safe to use them. The std::list maintains an element (pointed to by iHead) that is considered already read. For this algorithm to work even when the queue was just created, I add an empty T() element in the constructor of the LockFreeQueue (see Figure 1): LockFreeQueue() { list.push_back(T()); iHead = list.begin(); iTail = list.end(); } This Consume() method will likely heat up one of your CPUs red-hot to 100percent use if there are no elements in the queue. Nevertheless, this should have good performance when the queue is not empty. However, if you think of it, a queue that’s almost never empty is a sign of systemic trouble: It means the consumer is unable to keep pace with the producer, and sooner or later, the system is doomed to die of memory exhaustion. Call this approach NAIVE_POLLING. A friendlier Consume() function does some pooling and calls some sort of Listing One #include #include #include template struct WaitFreeQueue { void Produce(const T& t) { queue.Produce(t); cond.notify_one(); } bool Consume(T& t) { return queue.Consume(t); } T Consume(int wait_time = 1/*milliseconds*/) { T tmp; if (Consume(tmp)) return tmp; // the queue is empty, try again (possible waiting ) boost::mutex::scoped_lock lock(mtx); while (!Consume(tmp)) // line A { boost::xtime t; boost::xtime_get(&t, boost::TIME_UTC); AddMilliseconds(t, wait_time); cond.timed_wait(lock, t); // line B } return tmp; } private: LockFreeQueue queue; boost::condition cond; boost::mutex mtx; }; 44 Dr. Dobb’s Journal l www.ddj.com l July 2008 http://www.ddj.com
Table of Contents Feed for the Digital Edition of Dr. Dobb's Journal - July 2008 Dr. Dobb's Journal - July 2008 Contents Friday Night Fish Fry Alia Vox Developer Diaries Developer’s Notebook Engineers Without Borders Conversations Patricia Tries Event-Based Architectures Graphs Versus Objects Lock-Free Queues Dr. Dobb’s Architecture & Design World Java and the Nokia N10 Internet Tablet Effective Concurrency The Agile Edge Swaine’s Flames Dr. Dobb's Journal - July 2008 Dr. Dobb's Journal - July 2008 - (Page Belly1) Dr. Dobb's Journal - July 2008 - (Page Belly2) Dr. Dobb's Journal - July 2008 - Dr. Dobb's Journal - July 2008 (Page Cover1) Dr. Dobb's Journal - July 2008 - Dr. Dobb's Journal - July 2008 (Page Cover2) Dr. Dobb's Journal - July 2008 - Dr. Dobb's Journal - July 2008 (Page 1) Dr. Dobb's Journal - July 2008 - Contents (Page 2) Dr. Dobb's Journal - July 2008 - Contents (Page 3) Dr. Dobb's Journal - July 2008 - Friday Night Fish Fry (Page 4) Dr. Dobb's Journal - July 2008 - Friday Night Fish Fry (Page 5) Dr. Dobb's Journal - July 2008 - Friday Night Fish Fry (Page 6) Dr. Dobb's Journal - July 2008 - Friday Night Fish Fry (Page 7) Dr. Dobb's Journal - July 2008 - Alia Vox (Page 8) Dr. Dobb's Journal - July 2008 - Alia Vox (Page 9) Dr. Dobb's Journal - July 2008 - Developer Diaries (Page 10) Dr. Dobb's Journal - July 2008 - Developer Diaries (Page 11) Dr. Dobb's Journal - July 2008 - Developer’s Notebook (Page 12) Dr. Dobb's Journal - July 2008 - Developer’s Notebook (Page 13) Dr. Dobb's Journal - July 2008 - Engineers Without Borders (Page 14) Dr. Dobb's Journal - July 2008 - Engineers Without Borders (Page 15) Dr. Dobb's Journal - July 2008 - Engineers Without Borders (Page 16) Dr. Dobb's Journal - July 2008 - Engineers Without Borders (Page 17) Dr. Dobb's Journal - July 2008 - Conversations (Page 18) Dr. Dobb's Journal - July 2008 - Conversations (Page 19) Dr. Dobb's Journal - July 2008 - Patricia Tries (Page 20) Dr. Dobb's Journal - July 2008 - Patricia Tries (Page 21) Dr. Dobb's Journal - July 2008 - Event-Based Architectures (Page 22) Dr. Dobb's Journal - July 2008 - Event-Based Architectures (Page 23) Dr. Dobb's Journal - July 2008 - Event-Based Architectures (Page 24) Dr. Dobb's Journal - July 2008 - Event-Based Architectures (Page 25) Dr. Dobb's Journal - July 2008 - Event-Based Architectures (Page 26) Dr. Dobb's Journal - July 2008 - Event-Based Architectures (Page 27) Dr. Dobb's Journal - July 2008 - Event-Based Architectures (Page 28) Dr. Dobb's Journal - July 2008 - Event-Based Architectures (Page 29) Dr. Dobb's Journal - July 2008 - Graphs Versus Objects (Page 30) Dr. Dobb's Journal - July 2008 - Graphs Versus Objects (Page 31) Dr. Dobb's Journal - July 2008 - Graphs Versus Objects (Page 32) Dr. Dobb's Journal - July 2008 - Graphs Versus Objects (Page 33) Dr. Dobb's Journal - July 2008 - Graphs Versus Objects (Page 34) Dr. Dobb's Journal - July 2008 - Graphs Versus Objects (Page 35) Dr. Dobb's Journal - July 2008 - Graphs Versus Objects (Page 36) Dr. Dobb's Journal - July 2008 - Graphs Versus Objects (Page 37) Dr. Dobb's Journal - July 2008 - Graphs Versus Objects (Page 38) Dr. Dobb's Journal - July 2008 - Graphs Versus Objects (Page 39) Dr. Dobb's Journal - July 2008 - Graphs Versus Objects (Page 40) Dr. Dobb's Journal - July 2008 - Graphs Versus Objects (Page 41) Dr. Dobb's Journal - July 2008 - Graphs Versus Objects (Page 42) Dr. Dobb's Journal - July 2008 - Lock-Free Queues (Page 43) Dr. Dobb's Journal - July 2008 - Lock-Free Queues (Page 44) Dr. Dobb's Journal - July 2008 - Lock-Free Queues (Page 45) Dr. Dobb's Journal - July 2008 - Lock-Free Queues (Page 46) Dr. Dobb's Journal - July 2008 - Lock-Free Queues (Page 47) Dr. Dobb's Journal - July 2008 - Dr. Dobb’s Architecture & Design World (Page 48) Dr. Dobb's Journal - July 2008 - Dr. Dobb’s Architecture & Design World (Page 49) Dr. Dobb's Journal - July 2008 - Java and the Nokia N10 Internet Tablet (Page 50) Dr. Dobb's Journal - July 2008 - Java and the Nokia N10 Internet Tablet (Page 51) Dr. Dobb's Journal - July 2008 - Java and the Nokia N10 Internet Tablet (Page 52) Dr. Dobb's Journal - July 2008 - Java and the Nokia N10 Internet Tablet (Page 53) Dr. Dobb's Journal - July 2008 - Java and the Nokia N10 Internet Tablet (Page 54) Dr. Dobb's Journal - July 2008 - Java and the Nokia N10 Internet Tablet (Page 55) Dr. Dobb's Journal - July 2008 - Java and the Nokia N10 Internet Tablet (Page 56) Dr. Dobb's Journal - July 2008 - Effective Concurrency (Page 57) Dr. Dobb's Journal - July 2008 - Effective Concurrency (Page 58) Dr. Dobb's Journal - July 2008 - Effective Concurrency (Page 59) Dr. Dobb's Journal - July 2008 - The Agile Edge (Page 60) Dr. Dobb's Journal - July 2008 - The Agile Edge (Page 61) Dr. Dobb's Journal - July 2008 - The Agile Edge (Page 62) Dr. Dobb's Journal - July 2008 - The Agile Edge (Page 63) Dr. Dobb's Journal - July 2008 - Swaine’s Flames (Page 64) Dr. Dobb's Journal - July 2008 - Swaine’s Flames (Page Cover3) Dr. Dobb's Journal - July 2008 - Swaine’s Flames (Page Cover4)
For optimal viewing of this digital publication, please enable JavaScript and then refresh the page. If you would like to try to load the digital publication without using Flash Player detection, please click here.