user19551894
user19551894

Reputation:

Happens-Before Relationship - What is an atomic object talking about concurrency in C++?

https://timsong-cpp.github.io/cppwp/n4861/intro.races#8

An evaluation A is dependency-ordered before an evaluation B if (8.1) A performs a release operation on an atomic object M, and, in another thread, B performs a consume operation on M and reads the value written by A, or (8.2) for some evaluation X, A is dependency-ordered before X and X carries a dependency to B. [ Note: The relation “is dependency-ordered before” is analogous to “synchronizes with”, but uses release/consume in place of release/acquire. — end note ]

¿"Atomic object" is "something special" in C++ or is it just a name given to any variable in the context (when we talk about concurrency in c++) of concurrency in C++?

If it is something special, can you tell me what it is?

Upvotes: 1

Views: 180

Answers (3)

Useless
Useless

Reputation: 67723

¿"Atomic object" is "something special" in C++ or is it just a name given to any variable in the context (when we talk about concurrency in c++) of concurrency in C++?

Literally 5 paragraphs above the one you quoted is

3 The library defines a number of atomic operations (atomics) ...

4 All modifications to a particular atomic object M ...

where the first mention of an atomic object comes immediately after the first reference to atomic operations, which links to the section describing only two new classes (well, class templates plus specializations): std::atomic and std::atomic_ref.


An atomic object is, in the broadest terms (edit for the avoidance of doubt, this means with more generality than C++ or any individual language), an object to which we can make atomic (meaning "indivisible") updates. So, another thread could read the old value, or the new value, but never a mixture of both.

That's not sufficient to actually do very much without:

  1. either knowing something about a specific platform's memory subsystem (which would be non-portable) or also providing a way to specify the ordering constraints needed on a particular load or store
  2. providing some way to prevent the compiler reordering (or eliding) loads or stores inappropriately

All three of those things (indivisibility, explicit ordering and compiler control) are bundled together into the std::atomic and std::atomic_ref wrappers, with the necessary support from the C++ memory model.

Before this language support (the memory model plus the atomics library), the best we could do was write platform-specific code using intrinsics or assembler, or platform-specific libraries like pthreads.

Upvotes: 1

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275385

Prior to a relatively recent version of C++, atomic objects are just std::atomic stuff. It was simple. Now, it is more complex.

The introduction of atomic_ref changed this:

[atomics.ref.generic] 31.7/1 reads:

An atomic_­ref object applies atomic operations ([atomics.general]) to the object referenced by *ptr such that, for the lifetime ([basic.life]) of the atomic_­ref object, the object referenced by *ptr is an atomic object ([intro.races]).

So atomic objects are std::atomic<T> and family (std::atomic_bool etc), plus anything wrapped by a std::atomic_ref<T>. The std::atomic_ref<T> is not atomic, but the wrapped thing becomes so.

The idea is that these atomic objects are the objects for which atomic operations (which are a special kind of thread-safe operations in the C++ standard) can apply to.

The fact that "normal" objects that are no longer wrapped in atomic_ref are no longer atomic is important and tricky to think about. I suspect this rule exists because some platforms implement atomics using lock-based operations. On others, atomic operations can occur on most well-aligned memory.

std::atomic<int> a;
int b;

a is atomic, b is not.

{
   std::atomic_ref<int> x(b);

now b is an atomic object.

}

and now b is not an atomic object.

Upvotes: 2

ComicSansMS
ComicSansMS

Reputation: 54589

In the simplest possible terms, an atomic object is an object of type std::atomic<T> or std::atomic_ref<T>.

These objects provide special operations for fine-grained atomic access to data that are subject to special guarantees from the language with regards to inter-thread synchronization, which form the basis of the C++ memory model.

See [intro.multithread] and [atomics.general] as the relevant sections in the latest draft standard.

Upvotes: 1

Related Questions