While running Boost.Lockfree's tests, one of our compiler devs encountered the following failure:
freelist_test.cpp c:\wcfb01\binaries\x86chk\inc\atomic(659): error C2338: You've instantiated std::atomic<T> with sizeof(T) equal to 2/4/8 and alignof(T) < sizeof(T). Before VS 2015 Update 2, this would have misbehaved at runtime. VS 2015 Update 2 was fixed to handle this correctly, but the fix inherently changes layout and breaks binary compatibility. Please define _ENABLE_ATOMIC_ALIGNMENT_FIX to acknowledge that you understand this, and that everything you're linking has been compiled with VS 2015 Update 2 (or later). c:\wcfb01\binaries\x86chk\inc\atomic(669): note: see reference to class template instantiation 'std::_Atomic_base<_Ty,4>' being compiled with [ _Ty=boost::lockfree::detail::tagged_index ] e:\boost\boost\boost\lockfree\detail\freelist.hpp(608): note: see reference to class template instantiation 'std::atomicboost::lockfree::detail::tagged_index' being compiled e:\boost\boost\boost\lockfree\detail\freelist.hpp(609): note: see reference to class template instantiation 'boost::lockfree::detail::fixed_size_freelist
' being compiled call "C:\WCFB01\binaries\x86chk\bin\i386\vcvarsall.bat" x86 >nul cl /Zm800 -nologo @"..\bin.v2\libs\lockfree\test\freelist_test.test\msvc-latest\debug\threading-multi\freelist_test.obj.rsp"
...failed compile-c-c++ ..\bin.v2\libs\lockfree\test\freelist_test.test\msvc-latest\debug\threading-multi\freelist_test.obj...
with the following type:
class tagged_index { public: typedef boost::uint16_t tag_t; typedef boost::uint16_t index_t;
protected: index_t index; tag_t tag; };
This is by design - your tagged_index has align 2, size 4, triggering the need for my atomic alignment fix. As the static_assert advises, your code needs to define _ENABLE_ATOMIC_ALIGNMENT_FIX in order to pass.
If this has already been fixed in 1.61.0, then that's great (I haven't checked).
giving it a second thought, my interpretation of the standard suggests that that it is valid code that the compiler should accept. the standard (or n3290, which i have on my machine) tells me:
There is a generic class template atomic<T>. The type of the template argument T shall be trivially copy assignable and bitwise equality comparable.
i cannot find any wording which requires specific alignment requirements
for T. imho this is for a good reason: the type T might not be part of
your codebase, but coming from the API of a third-party library.
even if tagged_index is 2-byte aligned, it it would be perfectly valid
to use atomic
[Note: Operations that are lock-free should also be address-free. That is, atomic operations on the same memory location via two different addresses will communicate atomically. The implementation should not depend on any per-process state. This restriction enables communication by memory that is mapped into a process more than once and by memory that is shared between two processes. — end note ]
----- maybe something changed in the wording of the standard, but from what i can tell this change to msvc will reject valid code. so my suggestion is the following: * make atomic<T> lock-free depending on the address of the instance, use whatever fallback mechanism you have to emulate non-lock-free atomics. * using a spinlock-pool in the run-time library for emulating blocking atomic<>s to ensure that sizeof(T) == sizeof(atomic<T>). afaict the standard doesn't impose any restrictions on this, but leaves this open to the implementation. * issue a warning that T should be properly aligned to ensure that atomic<T> will always be lock-free. afaict you would then end up with a rather standard-compliant implementaton of atomic<T>. cheers, tim