'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 |