|
Boost Users : |
Subject: Re: [Boost-users] WG: [atomic] can it bechecked that boost::atomic<T> *v = reinterpret_cast<boost::atomic<T>*>(var); is safe?
From: Brian Budge (brian.budge_at_[hidden])
Date: 2014-09-15 14:05:54
On Mon, Sep 15, 2014 at 10:33 AM, Tim Odenthal <Tim.Odenthal_at_[hidden]
> wrote:
>
> On 15 Sep 2014, at 18:00, boost-users-request_at_[hidden] wrote:
>
> On Monday, September 15, 2014 07:31 PM, Tim Odenthal wrote:
>
> Dear experts,
>
> essentially, I use this type of reinterpret_cast for doubles, and it
> __seems__ to work fine. I compile-time check that the
> sizeof(boost::atomic<T>) == sizeof( T ), but is that enough to ensure that
> this will always work? Should/could I check alignment issues as well? Even
> if the "atomic_cast" function has a (small) run-time overhead, it would be
> very much worth it in my setting, where I actually want to safely add to a
> double at some location in memory. Obviously, I want to use boost::atomic
> to be system/compiler agnostic, since it's supposed to eventually run with
> clang, gcc, (linux, OS X) as well as MS compilers, and so far we didn't see
> the need to move to C++11...
>
>
> I'm not sure I can figure out what problem you're trying to solve.
>
>
> Well, essentially, I have an array of doubles that at exactly one point in
> the code needs to be added to where I cannot ensure that each thread only
> adds to its own part of the array, so I want to ensure that each addition
> there is executed atomically.
>
>
>
> I think the cast is probably "safe", but far less can be said of it when
> it's dereferenced. That would depend entirely on the type of var.
>
>
> Is *var actually a boost::atomic<T> in the first place? If it is, why
> are you erasing its type?
>
>
> No, as I was saying, itâs a double *.
>
>
> How can you be sure there is nobody else aliasing var or *var and then
> reading or writing it?
>
>
> That is actually a problem, but since I completely control that part of
> the code, I hope to not make that mistake ;-).
>
>
> If *var is not a boost::atomic<T>, reinterpret_cast isn't going to
> magically convert it, you have undefined behaviour. Of course, one
> effect of UB is that it __seems__ to work, until, presumably, it doesnât.
>
>
> But what, then, is the difference between an atomic<double>* and a normal
> double*, if the sizes (and possibly alignments) are the same?
>
> Hmmm, I just read up on what a reinterpret_cast<> is supposed to be good
> for, which is very little indeed, so it seems that the behaviour is
> undefined - but then there is no way to solve that problem? (So far I only
> ever used it to print the address of a pointer...)
> Since openMP allows for a pragma atomic, somehow, it seems that there
> should be a way. Using a simple spin_lock is way too slow (tested), since
> it doesnât lock a specific memory location, but essentially everything, and
> I suspect that more complicated locking schemes will be also more
> expensive, just for different reasons.
>
>
These functions are probably close to what you want:
http://en.cppreference.com/w/cpp/atomic
Note, however, that atomic_is_lock_free<double> is unlikely to be true for
most platforms; You can try to alias your memory with 64-bit integers, and
use compare_exchange to ensure atomicity (as opposed to fetch_add, which
could be used if you natively had integers).
Brian
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net