'How do I check for overflow after an Interlocked.Increment in C#?
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.
Solution 1:[1]
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.
Solution 2:[2]
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
- Little performance boost, because compiler won't check overflow.
- x2 space for keys
- Simpler and smaller code
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | Alex Zhukovskiy |
