commit d168eb73a23756642bdc80451ba206a345471f6a Author: Henrik Grubbström (Grubba) grubba@grubba.org Date: Sun Aug 5 11:21:52 2018 +0200
Thread.ResourceCount: Fixed mutex handling.
I'm not saying that this is not correct, I just want to make sure I understand the change. Can anyone elaborate on as to why this change is necessary/desirable?
Hi Stephen.
Condition variables work like this: You have some resource that multiple treads want to use (in your case the variable "_count"). To protect this resource for simultaneous access, you have a mutex. Before you read or write the resource, you take the mutex so that you get a consistent and private view of / control over it. If you decide that the resource is not in the state you want it, and that you need to wait for some other thread to modify the state for you before you can continue, you wait on the conditinal variable, which will temporarily relinquish the mutex during the wait. This way a different thread can take the mutex, update the state of the resource, and then signal the condition (which does not in itself release the mutex, but the signalled thread will be next in line once the mutex is released).
Before the change, you code did not follow this pattern. It examined and modified the resource outside of the mutex, and only took the mutex to wait or signal on the condition, which makes no sense.
For a simple example of how this can go wrong, consider a _count of 2 and two threads, one destroying a ResourceCountKey and the other executing wait_till_drained(1). Let's say that the second thread first looks at _count and sees that 2 > 1, thus deciding that it needs to wait. But it hasn't taken the mutex yet. So the first thread now runs, it can decrement _count to 1 and then take the mutex. After taking the mutex it sends the signal, and releases the mutex. The second thread can now take the mutex and wait on the condition variable. But the signal was already sent by the first thread, so the second thread missed it and will be waiting forever.
In order to prevent such races (which is the whole point of condition variables), the modification of the resource and the signal notifying modification of the resource must be performed inside the same mutex lock, and the examining of the resource and waiting for a signal that the resource has changed based on that examination must also happen inside the same mutex lock.
Wait:
1) take mutex lock 2) read/write resource 3) wait if needed, repeat from 2 3) release mutex lock
Signal:
1) take mutex lock 2) read/write resource 3) send signal 4) release mutex lock
Marcus Comstedt (ACROSS) (Hail Ilpalazzo!) @ Pike (-) developers forum wrote:
Condition variables work like this: You have some resource that
Ok, thanks!
I'll propagate the fix to 8.0 and I'll add some text loosely inspired by your explanation to the documentation of Thread.Condition in 8.1 and 8.0.
Thanks for working on the documentation! Please note however that 8.1 development should go to the "master" branch novadays. We probably forgot to make an announcement about that after the last conference... :-9
pike-devel@lists.lysator.liu.se