Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is initializing a atomic pointer atomic? What happens if initialization or memory allocation throws?

Tags:

c++

c++11

c++14

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?

like image 677
user888270 Avatar asked May 14 '18 09:05

user888270


2 Answers

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 constructing T should not throw but some user defined T 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.

like image 101
StoryTeller - Unslander Monica Avatar answered Nov 17 '22 02:11

StoryTeller - Unslander Monica


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.

like image 27
Gem Taylor Avatar answered Nov 17 '22 01:11

Gem Taylor