
The most important advantage for me is that it simplifies Project Invincible's build systems. In particular, for GNU/Linux I distribute source code rather than binaries (i.e. end users will have to compile the game themselves), but I had decided to pre-assemble my previous spinlock implementation to allow players to compile Project Invincible without having an assembler installed. That required me to implement a way to detect the architecture of the OS kernel so that the game will be linked to the right object code file...

I decided to license my new spinlock implementation, unlike the rest of Project Invincible's codebase, as public domain. (It is probably too short to be copyrightable anyway.)
Here it is: http://code.google.com/p/project-invincible/source/browse/trunk/common/spinlock.cpp?spec=svn418&r=418.
Atomic flags are guaranteed to be lock-free, i.e. to be implemented with atomic processor instructions instead of mutexes or other locks. For example, here is the assembly MSVC 2012 generated for the acquire() member function:
- Code: Select all
; Function compile flags: /Ogtp
; File f:\project invincible\project invincible\common\spinlock.cpp
; File c:\program files (x86)\microsoft visual studio 11.0\vc\include\xatomic.h
; File c:\program files (x86)\microsoft visual studio 11.0\vc\include\atomic
; File f:\project invincible\project invincible\common\spinlock.cpp
; COMDAT ?acquire@Spinlock@@QAEXXZ
_TEXT SEGMENT
?acquire@Spinlock@@QAEXXZ PROC ; Spinlock::acquire, COMDAT
; _this$ = ecx
; 18 : {
$LL2@acquire:
; File c:\program files (x86)\microsoft visual studio 11.0\vc\include\xatomic.h
; 2818 : return (_interlockedbittestandset(_Flag, 0)); /* set bit 0 */
lock bts DWORD PTR [ecx], 0
setb al
movzx eax, al
; File c:\program files (x86)\microsoft visual studio 11.0\vc\include\atomic
; 202 : return _ATOMIC_FLAG_TEST_AND_SET(&_My_flag, _Order);
test eax, eax
; File f:\project invincible\project invincible\common\spinlock.cpp
; 19 : while (lock.test_and_set(memory_order_acquire));
jne SHORT $LL2@acquire
; 20 : }
ret 0
?acquire@Spinlock@@QAEXXZ ENDP ; Spinlock::acquire
_TEXT ENDS