Defend against pathalogical thread-safety case.

If SecureObjectPool.NewId were to execute in a concurrent scenario where one thread actually was suspended while other threads were allowed to increment the counter enough to go through all 32-bits of values and the timing happened to be _just write_, we could theoretically return UnassignedId. This fixes it by looping until we get it right.
This commit is contained in:
Andrew Arnott 2014-11-11 10:50:05 -08:00
Родитель f3f9e2069c
Коммит 64929227e3
1 изменённых файлов: 9 добавлений и 8 удалений

Просмотреть файл

@ -31,11 +31,12 @@ namespace System.Collections.Immutable
/// </summary>
internal static int NewId()
{
int result = Interlocked.Increment(ref poolUserIdCounter);
if (result == UnassignedId)
int result;
do
{
result = Interlocked.Increment(ref poolUserIdCounter);
}
while (result == UnassignedId);
return result;
}
@ -46,12 +47,12 @@ namespace System.Collections.Immutable
{
public void TryAdd(TCaller caller, SecurePooledObject<T> item)
{
// Only allow the caller to recycle this object if it is the current owner.
if (caller.PoolUserId == item.Owner)
{
item.Owner = SecureObjectPool.UnassignedId;
AllocFreeConcurrentStack<SecurePooledObject<T>>.TryAdd(item);
}
// Only allow the caller to recycle this object if it is the current owner.
if (caller.PoolUserId == item.Owner)
{
item.Owner = SecureObjectPool.UnassignedId;
AllocFreeConcurrentStack<SecurePooledObject<T>>.TryAdd(item);
}
}
public bool TryTake(TCaller caller, out SecurePooledObject<T> item)