Skip to content

Commit

Permalink
Prevent lock contention for arbiters.
Browse files Browse the repository at this point in the history
  • Loading branch information
notgiven688 committed Dec 23, 2024
1 parent e1a99aa commit 92058c6
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 18 deletions.
38 changes: 23 additions & 15 deletions src/Jitter2/World.Detect.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Jitter2.Collision;
using Jitter2.Collision.Shapes;
using Jitter2.Dynamics;
Expand Down Expand Up @@ -417,30 +416,39 @@ private void Detect(IDynamicTreeProxy proxyA, IDynamicTreeProxy proxyB)
public void GetArbiter(ulong id0, ulong id1, RigidBody b0, RigidBody b1, out Arbiter arbiter)
{
ArbiterKey arbiterKey = new(id0, id1);
bool exists = arbiters.TryGetValue(arbiterKey, out Arbiter? arb);

lock (arbiters)
if (!exists)
{
ref Arbiter? arb = ref CollectionsMarshal.GetValueRefOrAddDefault(arbiters, arbiterKey, out bool exists);

if (!exists)
lock (memContacts)
{
if (!Arbiter.Pool.TryPop(out arb))
{
arb = new Arbiter();
}

deferredArbiters.Add(arb);
bool success = arbiters.TryAdd(arbiterKey, arb);

var h = memContacts.Allocate(true);
arb.Handle = h;
h.Data.Init(b0, b1);
h.Data.Key = arbiterKey;
arb.Body1 = b0;
arb.Body2 = b1;
}
if (success)
{
var h = memContacts.Allocate(true);
arb.Handle = h;
h.Data.Init(b0, b1);
h.Data.Key = arbiterKey;
arb.Body1 = b0;
arb.Body2 = b1;

Debug.Assert(arb != null && memContacts.IsActive(arb.Handle));
arbiter = arb;
Debug.Assert(arb != null && memContacts.IsActive(arb.Handle));

deferredArbiters.Add(arb);
}
else
{
Arbiter.Pool.Push(arb);
}
}
}

arbiter = arb!;
}
}
2 changes: 1 addition & 1 deletion src/Jitter2/World.Step.cs
Original file line number Diff line number Diff line change
Expand Up @@ -466,7 +466,7 @@ private void RemoveBrokenArbiters()

memContacts.Free(handle);
IslandHelper.ArbiterRemoved(islands, arb);
arbiters.Remove(handle.Data.Key);
arbiters.TryRemove(handle.Data.Key, out _);

arb.Body1.RaiseEndCollide(arb);
arb.Body2.RaiseEndCollide(arb);
Expand Down
5 changes: 3 additions & 2 deletions src/Jitter2/World.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#pragma warning disable CS8618 // InitParallelCallbacks() - https://github.com/dotnet/roslyn/issues/32358

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
Expand Down Expand Up @@ -103,7 +104,7 @@ public SpanData(World world)
/// </summary>
public SpanData RawData => new(this);

private readonly Dictionary<ArbiterKey, Arbiter> arbiters = new();
private readonly ConcurrentDictionary<ArbiterKey, Arbiter> arbiters = new();

private readonly ActiveList<Island> islands = new();
private readonly ActiveList<RigidBody> bodies = new();
Expand Down Expand Up @@ -366,7 +367,7 @@ public void Remove(Arbiter arbiter)
ActivateBodyNextStep(arbiter.Body2);

IslandHelper.ArbiterRemoved(islands, arbiter);
arbiters.Remove(arbiter.Handle.Data.Key);
arbiters.TryRemove(arbiter.Handle.Data.Key, out _);

brokenArbiters.Remove(arbiter.Handle);
memContacts.Free(arbiter.Handle);
Expand Down

0 comments on commit 92058c6

Please sign in to comment.