
On Mon, Jan 14, 2013 at 11:24 AM, Vicente J. Botet Escriba <vicente.botet@wanadoo.fr> wrote:
Le 14/01/13 04:23, Andrey Semashev a écrit :
1. You have the race condition I described in my previous post. The broadcast is missed if it happens when the other thread is executing at **** position.
I don't think so. The thread B has notified a commit in C*** or rollback in R***, the thread A could not be in //**** as the access to the flag is protected with the lock.
Ok, I'll leave this to you although I'm still not quite sure this is safe. I'll have to examine the algorithm closer later to resolve all my doubts.
2. If you use the double-check pattern with the lock, you don't need to CAS the flag.
Well this was the issue with the Trac ticket. The first check works only if T is such that the load/save is atomic. Maybe the access to the atomic flag inside the lock protected part could be relaxed I don't know all the possibilities of Boost.Atomic.
All loads and stores of atomic<> are atomic. The problem of split loads and stores should never occur when atomic<> is used, otherwise there is a severe bug in Boost.Atomic. Using CAS instead of a load/store does not make this guarantee any stronger. Note that this guarantee does not depend on whether the operation is done under lock or not.
3. I think your code will have worse performance because you lock the mutex whenever you are about to enter the execution block while mine code will only lock in case of contention. This difference is not in the most performance critical path but it still exists. However, I didn't perform any tests to confirm that.
I agree. But the condition variable needs that the code changing/getting the protect data needs to be protected with the same mutex that is used on the wait.
Yes, but not necessarily every modification of the control flag has to be protected.
IMHO, your previous implementation failed to do that as every access to the once flag in enter_once_region was not protected.
Yes, that was a valid optimization. The flag is checked the second time under the lock just before entering the wait on the condition variable. This keeps the algorithm correct while allowing to remove the lock from the fast path.