зеркало из https://github.com/App-vNext/corefx.git
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:
Родитель
f3f9e2069c
Коммит
64929227e3
|
@ -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)
|
||||
|
|
Загрузка…
Ссылка в новой задаче