++ and --
+= and -=
inc and dec
exchange and compare_and_swap
The atomic_counter<T> where T is a primitive integer type with 8, 16, or 32 bits is implemented
using genuine atomic arithmetic primitives. So, it is non-blocking, and it is the same size as
the underlying T. That is, sizeof(atomic_counter<T>)==sizeof(T). Furthermore, there is
no special constructor, destructor, or copy semantics.
This means that you can declare a structure containing atomic_counters and the struct will be binary compatible with the plain structure using ordinary integers.
The atomic_counter<T> where T is not a primitive integer type, but
the size is 8, 16, 32 or 64 bits, is implemented using a software transaction. It will sleep if it has to retry. It still has
the property of not needing any extra baggage, so sizeof(atomic_counter<T>)==sizeof(T) and there is
no special constructor, destructor, or copy semantics.
The general case where T is not 1, 2, 4, or 8 bytes is implemented using a critical_section. It has the usual implications of a class with interesting stuff inside it: you must construct, destruct, and copy it properly.
With no parameters, atomic_counter(), nothing special is done and the underlying initialization for the
T type is performed. For primitive integers, that means doing nothing.
The copy constructor is not surprising.
You can also construct given an underlying primitive value: atomic_counter (T). This allows reasonably
transparent use of an ordinary T when an atomic_counter is needed.
++ and --+= and -=inc and decexchange and compare_and_swap