1
General Discussion about just::thread / Re: ATOMIC_VAR_INIT
« on: February 17, 2011, 03:38:49 PM »
Got it. Thanks.
This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.
Yes, that's right. Didn't think about that. Thank you.Another thing that can be done is putting atomic classes betweenCode: [Select]#pragma pack(push)
#pragma pack(4)
// class atomic ...
#pragma pack(pop)
That wouldn't help: it just affects the layout of the atomic objects, not the alignment of the whole object.
MSVC is inconsistent: with #pragma pack(1) it obeys the alignment requirements sometimes, but not others.Thanks.
gcc always ignores alignment requirements with #pragma pack(1).
I'll put asserts in the atomic ops.
#pragma pack(push)
#pragma pack(4)
// class atomic ...
#pragma pack(pop)
hmmm..Yes, I guess you have a base class where the actual data is stored. The constructor might do that check. Alternatively you can do something like thisCode: [Select]template <typename T>
class atomic_base {
// T data;
__declspec (align(4)) T data;
};
The code already does that, so everything will be correctly aligned by default. However, if you use #pragma pack(1) then you're deliberately asking the compiler to ignore such alignment specifications, so it doesn't help.
#include <iostream>
#pragma pack(1)
struct X
{
char a;
__declspec (align(4)) long b;
};
bool is_aligned(void *ptr, int boundary)
{
return ((uintptr_t)ptr & (boundary - 1)) == 0;
}
int main()
{
X x;
std::cout << sizeof(X) << std::endl;
std::cout << is_aligned(&x.b, 4) << std::endl;
}
using this structure as amember of another unaligned structure will still keep our variable b properly aligned.template <typename T>
class atomic_base {
// T data;
__declspec (align(4)) T data;
};
#pragma pack(1)
struct X
{
std::atomic_char a;
std::atomic_long b;
};
As plain loads and stores are guaranteed to be atomic on x86 only in case of aligned read/write this structure may cause problems. In example above atomic_long is not properly aligned (I guess internal representation too), so I think it will be good idea to notify user (at least in debug mode) that library is not going to work as expected. Or alternatively you can explicitly align internal variable to the required boundary (I think this one is a better solution).#include <iostream>
#include <thread>
#include <atomic>
void thread1(std::atomic_long& x)
{
for (int i = 0; i < 1000000; ++i)
{
x.store(0);
long value = x.load();
assert(value == 0 || value == ~0);
}
}
void thread2(std::atomic_long& x)
{
for (int i = 0; i < 1000000; ++i)
{
x.store(~0);
long value = x.load();
assert(value == 0 || value == ~0);
}
}
#pragma pack(push)
#pragma pack(1)
struct X
{
char alignment;
std::atomic_long x;
};
#pragma pack(pop)
int main()
{
X arr[100];
for (int i = 0; i < 100; ++i)
{
std::cout << i << std::endl;
arr[i].x = 0;
std::thread thread(thread1, std::ref(arr[i].x));
thread2(arr[i].x);
thread.join();
}
}
Maybe. boost::thread_specific_ptr is slightly different again: though each pointer is freed automatically, you have to manually allocate and construct the object for each thread.It is, but at least it allows to have thread local objects and not to worry about freeing it up afterwards, which is simply impossible with __declspec(thread).
There is currently no support for TLS in just::thread. Given that the compilers supported by just::thread do have TLS support, I will consider adding it for a future release.Thanks for your answer Anthony.
though such a fence can also be achieved with a LOCKed RMW instruction, such as XCHG.On Visual Studio MemoryBarrier() function is implemented as a not locked RMW instruction.
LONG Barrier;Is it a typeo in MSDN?
__asm {
xchg Barrier, eax
}
Plain loads and stores on x86 give you acquire (for loads) and release (for stores) ordering. This is sufficient for many algorithms, but not for others. LFENCE and SFENCE are primarily of use with non-temporal stores such as MOVNTI, which don't obey the normal cache coherency rules (that's what "non-temporal" means, in effect --- they don't occur at a particular time).So it means that there is no analogs for sfence and lfence in C++1x, is it right?