diff --git a/src/Jitter2/World.Detect.cs b/src/Jitter2/World.Detect.cs index d38c7a42..70b41b7d 100644 --- a/src/Jitter2/World.Detect.cs +++ b/src/Jitter2/World.Detect.cs @@ -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; @@ -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!; } } \ No newline at end of file diff --git a/src/Jitter2/World.Step.cs b/src/Jitter2/World.Step.cs index aa47d481..1c0fee5d 100644 --- a/src/Jitter2/World.Step.cs +++ b/src/Jitter2/World.Step.cs @@ -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); diff --git a/src/Jitter2/World.cs b/src/Jitter2/World.cs index ecf68947..40472eac 100644 --- a/src/Jitter2/World.cs +++ b/src/Jitter2/World.cs @@ -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; @@ -103,7 +104,7 @@ public SpanData(World world) /// public SpanData RawData => new(this); - private readonly Dictionary arbiters = new(); + private readonly ConcurrentDictionary arbiters = new(); private readonly ActiveList islands = new(); private readonly ActiveList bodies = new(); @@ -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);