7.1 Atomic::Counter

The Atomic::Counter class is an atomic counter. The counter is a signed integer with a useful range of 31 bits (see Figure 7.1). Assume this is true when writing cross platform code. Don’t rely on the fact that on some processors the atomic counter range is 32 bits. All operations are implemented in assembler and guaranteed to be executed atomically (i.e: as if it was one unsecable instruction). Atomic counters can be used in single threaded as well as in multi-threaded applications. The atomicity of the operations guarantees that the counter is modified and eventually tested without race conditions.

On some processors (Sparc to not name them) there are only some rudimentary atomic support instructions, and the implementation had to be done using spinlock techniques. This influences:

Performance:
Spinlocks are basically while loops. They consume CPU resources waiting on a lock to be released if the counter is already in use. This lock must then be acquired to perform the actual computation. The assembler implementation tries to minimize the instruction number to keep the cost of data protection as low as possible.
Range:
The lock information costs one bit, taken from the counter. Thus the guaranteed cross platform useful range of an atomic counter is 31 bits.


Graphic browser needed to see picture
Figure 7.1: Atomic counter bit layout on processors without locking instructions.


Synopsis


  #include <lyric/Atomic.Counter.hpp>
  
  class Atomic::Counter
  {
  public:
    ~Atomic::Counter ();
    Atomic::Counter (int32 val = 0);
    static Range<int32> range ();
    void inc ();
    void dec ();
    bool inctz ();
    bool dectz ();
  private:
    // Disable cloning
    Atomic::Counter (const Atomic::Counter& counter);
    Atomic::Counter& operator = (const Atomic::Counter& counter);
  };


Description


˜Atomic::Counter ()
Destroys this atomic counter, releasing all used resources.

Atomic::Counter (uint32 val = 0)
Constructs this atomic counter. The optional value argument can be given to set the initial value of this counter. Without the initial value argument, this atomic counter is initialized to zero.

Range<int32> range () static
Returns the cross-platform useful range of an atomic counter. See Section 6.6. The returned range stores the smallest 31 bit netagive integer as minimum, and the largest 31 bit positive integer as maximum. However, during the use of an atomic counter there is no enforced range checking: the returned range is informative.

void inc ()
Atomically increases this counter by one.

void dec ()
Atomically decreases this counter by one.

bool inctz ()
Atomically increases this counter by one and tests if the resulting value stored in this counter is zero. Returns true if this counter stores zero after the increment, false if not.

bool dectz ()
Atomically decreases this counter by one and tests if the resulting value stored in this counter is zero. Returns true if this counter stores zero after the decrement, false if not.