Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.
/ corefx Public archive

Commit

Permalink
More thread safety
Browse files Browse the repository at this point in the history
  • Loading branch information
pakrym committed Mar 1, 2018
1 parent ebbb756 commit 4eecbab
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ public void SetMemory(OwnedMemory<byte> buffer)
public void SetMemory(OwnedMemory<byte> ownedMemory, int start, int end, bool readOnly = false)
{
_ownedMemory = ownedMemory;
_ownedMemory.Retain();

AvailableMemory = _ownedMemory.Memory;

Expand All @@ -75,6 +74,7 @@ public void SetMemory(OwnedMemory<byte> ownedMemory, int start, int end, bool re
public void ResetMemory()
{
_ownedMemory.Release();
_ownedMemory.Dispose();
_ownedMemory = null;
AvailableMemory = default;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ private sealed class ArrayMemoryPoolBuffer : OwnedMemory<T>
public ArrayMemoryPoolBuffer(int size)
{
_array = ArrayPool<T>.Shared.Rent(size);
_refCount = 1;
}

public sealed override int Length => _array.Length;
Expand Down Expand Up @@ -80,28 +81,30 @@ public sealed override MemoryHandle Pin(int byteOffset = 0)

public sealed override void Retain()
{
if (IsDisposed)
ThrowHelper.ThrowObjectDisposedException_ArrayMemoryPoolBuffer();

Interlocked.Increment(ref _refCount);
while (true)
{
int currentCount = Volatile.Read(ref _refCount);
if (currentCount <= 0) ThrowHelper.ThrowObjectDisposedException_ArrayMemoryPoolBuffer();
if (Interlocked.CompareExchange(ref _refCount, currentCount + 1, currentCount) == currentCount) break;
}
}

public sealed override bool Release()
{
if (IsDisposed)
ThrowHelper.ThrowObjectDisposedException_ArrayMemoryPoolBuffer();

int newRefCount = Interlocked.Decrement(ref _refCount);
if (newRefCount == 0)
while (true)
{
Dispose();
int currentCount = Volatile.Read(ref _refCount);
if (currentCount <= 0) ThrowHelper.ThrowObjectDisposedException_ArrayMemoryPoolBuffer();
if (Interlocked.CompareExchange(ref _refCount, currentCount - 1, currentCount) == currentCount)
{
if (currentCount == 1)
{
Dispose();
return false;
}
return true;
}
}

// Other thread already disposed
if (newRefCount < 0)
ThrowHelper.ThrowObjectDisposedException_ArrayMemoryPoolBuffer();

return newRefCount != 0;
}
}
}
Expand Down
4 changes: 1 addition & 3 deletions src/System.Memory/src/System/Buffers/ArrayMemoryPool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@ public sealed override OwnedMemory<T> Rent(int minimumBufferSize = -1)
else if (((uint)minimumBufferSize) > s_maxBufferSize)
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.minimumBufferSize);

var buffer = new ArrayMemoryPoolBuffer(minimumBufferSize);
buffer.Retain();
return buffer;
return new ArrayMemoryPoolBuffer(minimumBufferSize);
}

protected sealed override void Dispose(bool disposing) {} // ArrayMemoryPool is a shared pool so Dispose() would be a nop even if there were native resources to dispose.
Expand Down

0 comments on commit 4eecbab

Please sign in to comment.