If i declare and define a atomic pointer in one go like -
std::atomic<int*> iptr = new int(1);
std::atomic<T*> iptr = new T();
As I understand the whole operation is not atomic.
new T() involves assigning memory, constructing the T object and then it will be atomically assigned to iptr. T may be trivially constructible in which case constructing T should not throw but some user defined T MAY throw.
What if in between T construction or memory assignment some other thread uses iptr?
Is this operation really atomic? One way to make it atomic is breaking the declaration and definition e.g.
T* temp = new T();
std::atomic<T*> iptr = temp;
Is there any other way to do the same thing atomically? Is my understanding flawed?
new T()
involves assigning memory,
Yes.
constructing the
T
object
Yes.
and then it will be atomically assigned to iptr.
Exactly (almost, it's the address of the object that's used here). It's used to initialize the atomic after the memory allocation and construction is done.
T
may be trivially constructible in which case constructingT
should not throw but some user definedT
MAY throw.
And if it does, the initialization of the atomic won't be reached. The new
expression doesn't leak memory if a c'tor throws, it calls the proper deallcoation function. So your temporary, and the direct use of the new expression, have the exact same semantics.
The creation of the new unnamed object is not atomic, but it doesn't need to be. [As stated above, any exception will just impact the lifetime of the temporary object that got created before it is assigned to the atomic, and should clean up fine.]
The assignment of that temporary pointer to your atomic pointer is atomic.
My big concern is that as it stands your code can't detect if another thread did the assignment, so you then have to consider using testandset or swap. Then you have the hassle that the test/swap failed, and you have a temporary pointer to an object you don't need any more.
If you use a local variable (rather than an unnamed temporary) you get a chance to clean that up.
If you use a smart pointer for the atomic and the temporary it will self-destruct.
However, in many cases it is better if you don't create the temporary object unless you really need it, but that then means having a mutex across the whole creation, but you can do a lightweight check before entering the mutex. This is more like what singleton static variables do.
there is no real disadvantage if you are creating a singleton, as the other threads would have to wait anyway.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With