On Friday, 17 May 2013 at 21:06:30 UTC, Diggory wrote:
I think we all understand it's not going to catch every race condition, or even a given race condition every time, ie. it can't prove that the code is correct.

What it can do however is prove that code is incorrect. If the unit test fails there is definitely something wrong with the code, therefore it's a useful test to have.

The most obvious case is if there is a change to the singleton code which accidentally creates a race condition. Any chance of detecting that in a unit test is better than no chance of detecting it.

Exactly!

Anyways, I've updated the gist with an even better solution, that gave me 100% accuracy even when playing 4 video files.

I added a static shared counter that counts how many threads have passed the barrier - every thread has to increment it immediately after it passes the barrier. The constructor, instead of a single call to `sleep()`, calls `sleep()` until the counter reaches the number of threads. So, this is what happens:

1) 10 threads are started, each stops at the barrier waiting for the others. 2) Once all the threads have reached the barrier, threads are starting to get released(from the barrier, not from memory).
3) Each thread released from the barrier increments the counter.
4) At least one thread passes the singleton checks, enters the constructor and goes into a loop where it calls `sleep()` all of the threads got a chance to run again. 6) Once all the threads got that chance, all the threads stuck in the constructor get released from the loop.

Now, theoretically this unit test is not 100% accurate. If all the threads except one get switched out between step 3 and step 4 - that is, after they increment the counter but before they pass the singleton checks - then by the time those threads will run again, the one other thread gets to initiate the singleton and write the __gshared instance field - which means the other threads won't pass the singleton checks and won't create more instances, and the unit test won't fail even if the implementation is broken.

Now, while theoretically possible, this scenario is far fetched in reality. The window where a thread needs to be switched is very short, and placed immediately after it gets switched in. The amount of work the thread does in that window after it got switched in is smaller(or at least not much larger) than the work needed for the context switch, so no sane operation system should switch it out in that window - let alone switch out nine such threads.

Reply via email to