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