From 34119208d060c409a0eea53075cf07b3fde057e6 Mon Sep 17 00:00:00 2001 From: sakno Date: Fri, 15 Mar 2024 22:24:33 +0200 Subject: [PATCH] Optimized index selection --- .../Collections/Concurrent/IndexPool.cs | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/DotNext.Threading/Collections/Concurrent/IndexPool.cs b/src/DotNext.Threading/Collections/Concurrent/IndexPool.cs index b8e3e5bcc..6d8d72dcf 100644 --- a/src/DotNext.Threading/Collections/Concurrent/IndexPool.cs +++ b/src/DotNext.Threading/Collections/Concurrent/IndexPool.cs @@ -3,6 +3,7 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Numerics; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; namespace DotNext.Collections.Concurrent; @@ -73,19 +74,21 @@ public readonly bool TryPeek(out int result) /// public bool TryTake(out int result) { - ulong current, newValue = Volatile.Read(in bitmask); - do - { - result = BitOperations.TrailingZeroCount(current = newValue); + return TryTake(ref bitmask, maxValue, out result); - if (result > maxValue) - return false; + static bool TryTake(ref ulong bitmask, int maxValue, out int result) + { + var current = Volatile.Read(in bitmask); + for (ulong newValue; ; current = newValue) + { + newValue = current & (current - 1UL); // Reset lowest set bit, the same as BLSR instruction + newValue = Interlocked.CompareExchange(ref bitmask, newValue, current); + if (newValue == current) + break; + } - newValue = current ^ (1UL << result); + return (result = BitOperations.TrailingZeroCount(current)) <= maxValue; } - while ((newValue = Interlocked.CompareExchange(ref bitmask, newValue, current)) != current); - - return true; } ///