How do I check for overflow after an Interlocked.Increment in C#?

3k views Asked by At

What is the correct way to check for an overflow after a call to Interlocked.Increment?

I have an ID generator that generates unique ids during the program's execution, and currently I test if the increment returned zero.

public static class IdGenerator {
    private static int _counter = 0;
    
    public static uint GetNewId() {
        uint newId = (uint)System.Threading.Interlocked.Increment(ref _counter);
        if (newId == 0) {
             throw new System.Exception("Whoops, ran out of identifiers");
        }
        return newId;
    }
}

Given the rather large number of IDs that I generate per run, it is possibile (on an exceptionally large input) that the _counter will overflow when incremented, and I want to throw an exception in that case (crash early to ease debugging).

Excerpt from Microsoft's documentation:

This method handles an overflow condition by wrapping: if location = Int32.MaxValue, location + 1 = Int32.MinValue. No exception is thrown.

2

There are 2 answers

5
SLaks On BEST ANSWER

Just check whether newId is Int32.MinValue (before casting to uint) and throw an exception.

The only way to get MinValue from an increment is through overflow.

0
Alex Zhukovskiy On

Consider using unchecked

public static class IdGenerator
{
    private static int _counter;

    public static uint GetNewId()
    {
        uint newId = unchecked ((uint) System.Threading.Interlocked.Increment(ref _counter));
        if (newId == 0)
        {
            throw new System.Exception("Whoops, ran out of identifiers");
        }
        return newId;
    }
}

In this case you get

  1. Little performance boost, because compiler won't check overflow.
  2. x2 space for keys
  3. Simpler and smaller code