I am having trouble understanding the implications of the MSDN documentation for the Interlocked Variable Access family of functions. I use InterlockedExchange for setting and InterlockedCompareExchange for getting a member variable that is used by multiple threads.
The member is inside a 1 byte packed class:
#pragma pack(1)
class MyClass {
char _;
long m_MyMember;
// ...
}
So the member is set by
InterlockedExchange(&m_MyMember, 1);
and gotten by
long value = InterlockedCompareExchange(&m_MyMember, 0, 0);
InterlockedExchange documentation does not refer to alignment in any way (Strg+F "align"), but InterlockedCompareExchange does:
The parameters for this function must be aligned on a 32-bit boundary; otherwise, the function will behave unpredictably on multiprocessor x86 systems and any non-x86 systems.
However, as I understand it, the parameters are all stack variables, because one could rewrite the above call
long *ptr = &m_MyMember;
long zero = 0;
long value = InterlockedCompareExchange(ptr, zero, zero);
So we have block local auto storage class variables. All perfectly 4 byte aligned regardless of the class m_MyMember resides in. Of course, I assume that this is wrong and it is meant that the address behind ptr must be aligned on a 4 byte boundary.
So my questions are:
- Is InterlockedExchange really alignment agnostic or is this a let out in the documentation?
- Can you confirm that not literally the parameters, but the address behind the long* has to be 4 byte aligned (I cannot assume how the other parameters could not be 4 byte aligned because they are stack variables)?
- If the answer to 2 is yes: How could this be resolved? Changing the surrounding class' alignment is not an option, neither is c++ 11 atomic or boost (all due to corporate limitations and required compilability for msvc10 to msvc14).
I considered declaring m_MyMember volatile and using critical sections to access it. Although I would like it better to properly declare m_MyMember to be aligned as needed because those Interlocked Variable Access functions are all around the given code base and I'd like not to add an extra companion CS to every variable.