RecyclableList.IndexOf parallel performance improvements.
This commit is contained in:
1 parent
99600d4854
commit
3db10d7602
21 files changed
+4282
-511
No files matched your search
@@ -0,0 +1,117 @@
|
||||
using Microsoft.Extensions.ObjectPool;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Recyclable.Collections.Parallel
|
||||
{
|
||||
public sealed class BarrierSlimmer : IDisposable
|
||||
{
|
||||
private static readonly ObjectPool<BarrierSlimmer> _defaultPool = new DefaultObjectPool<BarrierSlimmer>(new DefaultPooledObjectPolicy<BarrierSlimmer>());
|
||||
private ObjectPool<BarrierSlimmer>? _assignedPool;
|
||||
private readonly SpinLock _lock = new(false);
|
||||
|
||||
public bool HasParticipants;
|
||||
public int Participants;
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public void AddParticipant()
|
||||
{
|
||||
bool isLocked = false;
|
||||
_lock.Enter(ref isLocked);
|
||||
|
||||
Participants++;
|
||||
if (Participants == 1)
|
||||
{
|
||||
HasParticipants = true;
|
||||
}
|
||||
|
||||
if (isLocked)
|
||||
{
|
||||
_lock.Exit(false);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public void RemoveParticipant()
|
||||
{
|
||||
if (!HasParticipants)
|
||||
{
|
||||
ThrowNoMoreParticipants();
|
||||
}
|
||||
|
||||
bool isLocked = false;
|
||||
_lock.Enter(ref isLocked);
|
||||
|
||||
Participants--;
|
||||
if (Participants == 0)
|
||||
{
|
||||
HasParticipants = false;
|
||||
}
|
||||
|
||||
if (isLocked)
|
||||
{
|
||||
_lock.Exit(false);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ThrowNoMoreParticipants()
|
||||
{
|
||||
throw new InvalidOperationException("There are no more participants. The operation is not allowed");
|
||||
}
|
||||
|
||||
public BarrierSlimmer()
|
||||
{
|
||||
_lock = new(false);
|
||||
}
|
||||
|
||||
public BarrierSlimmer(int participants)
|
||||
{
|
||||
_lock = new(false);
|
||||
Participants = participants;
|
||||
HasParticipants = participants > 0;
|
||||
}
|
||||
|
||||
public static BarrierSlimmer Create(int participants)
|
||||
{
|
||||
var result = _defaultPool.Get();
|
||||
result.Participants = participants;
|
||||
result.HasParticipants = participants > 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
var assignedPool = _assignedPool;
|
||||
_assignedPool = null;
|
||||
assignedPool?.Return(this);
|
||||
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
public void SignalAndWait()
|
||||
{
|
||||
RemoveParticipant();
|
||||
|
||||
//if (!HasParticipants)
|
||||
//{
|
||||
// return;
|
||||
//}
|
||||
|
||||
//if (!HasParticipants)
|
||||
//{
|
||||
// return;
|
||||
//}
|
||||
|
||||
//if (!HasParticipants)
|
||||
//{
|
||||
// return;
|
||||
//}
|
||||
|
||||
// SpinWait.SpinUntil(() => HasParticipants);
|
||||
var waitSpinner = new SpinWait();
|
||||
while (HasParticipants)
|
||||
{
|
||||
waitSpinner.SpinOnce(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user