Skip to content

Commit

Permalink
Fix a bug where double locking would actually deadlock the entry neve…
Browse files Browse the repository at this point in the history
…r releasing it
  • Loading branch information
Wsm2110 committed Jul 30, 2024
1 parent 393bc65 commit 1ef9347
Showing 1 changed file with 22 additions and 21 deletions.
43 changes: 22 additions & 21 deletions src/Concurrent/CMap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -281,20 +281,25 @@ public bool Update(TKey key, TValue newValue)
{
// Retrieve the entry from the table at the calculated index
ref var entry = ref Find(table.Entries, index);

// If the entry's metadata and key match, proceed with the update
if (h2 == entry.Meta && _keyComparer.Equals(key, entry.Key))
{
// Guarantee that only one thread can access the critical section at a time
entry.Enter();

var result = false;

if (h2 == entry.Meta)
{
// Perform the critical section: update the value
entry.Value = newValue;
entry.Exit();
return true;
result = true;
}

// Release lock
entry.Exit();

return result;
}

// If the entry indicates an empty bucket, the key does not exist in the table
Expand Down Expand Up @@ -392,13 +397,13 @@ public bool Remove(TKey key)
{
var hashcode = key.GetHashCode(); // Calculate the hash code for the given key
byte jumpDistance = 0; // Initialize jump distance for quadratic probing
var h2 = _table.H2(hashcode); // Calculate the secondary hash

start:

var table = _table; // Get the current state of the table
var index = table.GetBucket(hashcode); // Calculate the initial bucket index
var h2 = table.H2(hashcode); // Calculate the secondary hash


do
{
// Retrieve the entry from the table at the calculated index
Expand All @@ -410,28 +415,24 @@ public bool Remove(TKey key)
// Guarantee that only one thread can access the critical section at a time
entry.Enter();

bool result = false;

if (h2 == entry.Meta)
{
// reset current entry
entry.Meta = _tombstone;
entry.Key = default;
entry.Value = default;

// Check if the table has been resized during the operation
if (_table != table)
{
// If resized, restart with the new table
jumpDistance = 0;
entry.Exit();
goto start;
}

entry.Exit();
entry.Value = default;

// Decrease counter by 1
_counter.Decrement();

return true;
result = true;
}

// Release lock
entry.Exit();

return result;
}

// If the entry indicates an empty bucket, the key does not exist in the table
Expand Down Expand Up @@ -467,13 +468,13 @@ public bool Remove(TKey key, out TValue value)
{
var hashcode = key.GetHashCode(); // Calculate the hash code for the given key
byte jumpDistance = 0; // Initialize jump distance for quadratic probing
var h2 = _table.H2(hashcode); // Calculate the secondary hash

start:

var table = _table; // Get the current state of the table
var index = table.GetBucket(hashcode); // Calculate the initial bucket index
var h2 = table.H2(hashcode); // Calculate the secondary hash


do
{
// Retrieve the entry from the table at the calculated index
Expand Down

0 comments on commit 1ef9347

Please sign in to comment.