Boost logo

Boost :

Subject: Re: [boost] [lockfree] _ENABLE_ATOMIC_ALIGNMENT_FIX for VS 2015 Update 2
From: Tim Blechmann (tim_at_[hidden])
Date: 2016-05-10 13:35:45

> 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::atomic<boost::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<T,NodeStorage>' 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<tagged_index>. the implementation should work, it is just
not guaranteed that an instance is_lock_free(). i suppose that this is
exactly the reason why atomic::is_lock_free() is an instance method and
not a class method: depending on the address of the instance, the
implementation could be lock-free or not. the code path which is not
lockfree might use a spinlock pool, located in the run-time library.

this would be allowed because:

> [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>.


Boost list run by bdawes at, gregod at, cpdaniel at, john at