@fanbaby: You know what, cut the snide remarks. This is a useful post, but personal attacks (yes, I took the snide remark personally) aren't warranted on any public forum. I know you're a closed minded zealot, but you can at least have manners.
C++ has a standard. There are multiple companies implementing this standard. Yes, the GNU stuff is used everywhere, and could just as easily be seen as the WebKit of the C++ compiler world. Why doesn't everyone just use that?
Well, problems in the standard are discovered when there are multiple implementations. The standard becomes stronger. Extensions are made in different implementations, some of which get moved back into the standard, making it stronger. It's beneficial to have multiple implementations and a single standard.
The same is true for web browsers. A single standard is good. A single implementation is not. End of story.
But, it's evident now, you're real argument is about Open Source. Sorry, I don't care to be a part of that debate, as most people have taken sides and are now close minded. I don't take sides in this debate. We need both, and neither is better than the other.
@dc0d: That shouldn't be an issue. Threads run synchronously, so as long as you're not doing anything within the lock that would cause another lock you're fine. In POSIX the mutex isn't reentrant either, and it doesn't cause problems in usage. Your SpinMutex isn't reentrant either. If you call Lock twice from the same thread you'll deadlock.
I found this, which is an interesting benchmark. http://blog.moxen.us/2010/08/22/lock-spinlock-and-compareexchange-performance/
His findings are different from yours, which shows that the performance characteristics are very dependent upon usage scenarios. In general, the Monitor is going to be a highly efficient synchronization mechanism. You've just discovered a scenario where there's probably low contention and the time in the lock is smaller than the overhead of the lock itself so the synchronization became your hotpoint (again, I assume you've profiled and know this to be true). That's exactly what SpinLock is for. There's not a huge difference between SpinLock and your SpinMutex in implementation, but the differences are likely to mean SpinLock will outperform your SpinMutex, and again, you won't have to maintain the code. Synchronization concepts are pretty heady, and any time you don't have to create your own and maintain it you'll be better off.
If this is truly a hotspot, though, I still contend lock free and/or pre-caching will provide you the best performance.
Oh, BTW, .NET already has a SpinLock. http://msdn.microsoft.com/en-us/library/system.threading.spinlock(v=vs.110).aspx
The caveats on when to use it are important and would apply to your implementation as well.
I don't care how smart you are, everyone gets caught off guard now and then. I'll admit to having clicked on something and while the browser was still opening I realized how stupid it was, as the email was a fairly obvious phish.
There were a few tells in this attempt. It's not the best grammar (the sentence is awkward and it's missing a period). Looks legit enough to be a personal correspondence, but not legit enough to be a form email, which an acknowledgement of receipt would be. For that matter, form mails will generally come from an address that's not associated with a person, only with the company. I'd have suspected phishing here.
Hey, I have no problems with you using the above class. I see no problems with the implementation. I just wouldn't recommend use it as a drop in replacement for any of the existing synchronization concepts. Use it only when you believe you really do have a performance problem and can't see anyway to change algorithms. In your case, I still think a mostly lock free approach would work better.
I wouldn't call a sequential ID a Guid. If it's truly a sequential ID you should be able to implement it using Interlocked and be entirely lock free. Not knowing the details, if that's not possible then the scheme I suggested where you pre-allocate values to avoid frequent locks would likely provide you an even more significant performance gain over using a spin lock.
I'd give better advice if I understood more about what you're trying to do. Why does the ID need to be sequential? How many do you generate and how frequently? What are the hard requirements on uniqueness (i.e. is it unique within a single process, from different processes, from different runs, etc.)? What are the requirements on the structure of this ID?
@kettch: For that matter, why didn't we all stay with Mosaic?
I'll say it again. Standards are good, single implementations are bad. "But it's easier for developers" is a BS argument, even if you believe that in theory. None of the WebKit based browsers behave exactly the same, and you have to test in each anyway.
Finally did some research. The Monitor isn't implemented as I expected it would be, and you probably can get much better performance out of a spin lock. Rather than writing your own you could use a SemaphoreSlim. That probably still would have a bit more overhead than your implementation here, but I'd bet not enough to make the cost of creating/maintaining your own spin lock worth while. Given your description, however, I wonder if you'd not be better suited with a different approach all together. For starters, I don't know what you mean by a generator... why aren't you using Guid.NewGuid? In any case, just changing the granularity of your lock is likely to be your best solution here. If it's non-trivial to do this than you could probably create multiple Guids at once and cache them for future calls, allowing a non-blocking implementation for the majority of the calls. That would cost some memory but would outperform even a spin lock.
I haven't looked it up to verify, but it was my understanding that the monitor lock utilized a CRITICAL_SECTION under the hood. The Win32 CRITICAL_SECTION is implemented via compare/exchange and a spin wait. I doubt you're improving performance over just using a monitor.
The difference between a CRITICAL_SECTION (user level synchronization) and a MUTEX (kernel level synchronization) is tricky. Generally the CRITICAL_SECTION will outperform the MUTEX, but I've seen code where the reverse held true. Honestly, though, if the synchronization object is the cause of your performance problems (profile, profile, profile) then you're almost certainly better off looking for a lock free implementation rather than looking to micro-optimize the synchronization itself. There's just not enough direct overhead in any of the synchronization objects for micro-optimizations to make much of a difference, generally.