Okay, enough procrastination; it's time to write this thing.
So, it's not been a good week, as far as coding has been concerned. Rewriting the atomic functions is turning out to be a major pain, as I'm not really sure what the optimal way to structure my code is. I want to support at least x86-32, x86-64, PPC32, and PPC64. I also want to support at least VC++ and GCC (which uses AT&T style assembly). So, how many copies of the functions do I have to write? Well, I'd rather not think about that :P Then there's the complication that VC++ does not support x86-64 inline assembly, meaning that at the very least I have to write those functions in an ASM file and compile it with ML64 (MASM 64). As well, as of last night, the x86-32 functions were in an ASM file to be compiled with ML (MASM).
As if that wasn't enough trouble, Merlin just brought to my attention that VS 2005 contains compiler intrinsics for the atomic functions. Intrinsics, of course, mean that the compiler could insert the instructions directly into the calling functions, without the need to call another function such as mine. As this is a serious benefit to performance, and performance is one of my biggest goals with LibQ, I'll definitely want to use those instead of my own assembly functions, when compiled with VS 2005.
So, what else could go wrong? Well, plenty, it turns out. First of all, I noticed a design flaw in my POSIX event implementation. It wasn't immediately obvious because the event works most of the time. The problem comes when one thread tries to reset the event just after another thread set it. Setting it should release at least one thread waiting on the event, even if the event is subsequently reset. But in our implementation, in order for a thread to be released from a wait, the event must remain signaled until that thread gets the CPU and checks the status of the event. If a second thread resets the event before this occurs (which is not unreasonable, given the latency associated with bringing threads out of wait), the threads would remain waiting indefinitely. So condition variables are not the way to go. I've written an alternate version of the event class which does not have this problem; it also doesn't have something else, due to the nature of the implementation: support for wait timeouts. So, I guess that means I'm gonna have to remove timed waits for both the Windows and POSIX implementations, to keep the feature set identical.
Lastly, some features were removed from the mutex class. I had originally said that, because the POSIX mutex lacked some features that we wanted - namely, the ability to spin before going into wait - we'd simply write our own implementation with the desired features. The problem with this is that I still want to support condition variables in LibQ, and POSIX condition variables require a mutex - a POSIX mutex. So, I don't have much choice but to use a POSIX mutex for the POSIX version of the mutex class, to allow it to interoperate with the condition variable later. I chose to leave the spinning feature in the Windows version, however, to benefit from it where possible, and simply ignore it in the POSIX version (leaving the interface identical in both cases).