Backends: Metal: Add dispatch synchronization. (#5447)
diff --git a/backends/imgui_impl_metal.mm b/backends/imgui_impl_metal.mm
index 4a9feaf..23805b2 100644
--- a/backends/imgui_impl_metal.mm
+++ b/backends/imgui_impl_metal.mm
@@ -12,6 +12,8 @@
 
 // CHANGELOG
 // (minor and older changes stripped away, please see git history for details)
+//  2022-07-05: Metal: Add dispatch synchronization.
+//  2022-06-30: Metal: Use __bridge for ARC based systems.
 //  2022-06-01: Metal: Fixed null dereference on exit inside command buffer completion handler.
 //  2022-04-27: Misc: Store backend data in a per-context struct, allowing to use this backend with multiple contexts.
 //  2022-01-03: Metal: Ignore ImDrawCmd where ElemCount == 0 (very rare but can technically be manufactured by user code).
@@ -296,8 +298,11 @@
             ImGui_ImplMetal_Data* bd = ImGui_ImplMetal_GetBackendData();
             if (bd != NULL)
             {
-                [bd->SharedMetalContext.bufferCache addObject:vertexBuffer];
-                [bd->SharedMetalContext.bufferCache addObject:indexBuffer];
+                @synchronized(bd->SharedMetalContext.bufferCache)
+                {
+                    [bd->SharedMetalContext.bufferCache addObject:vertexBuffer];
+                    [bd->SharedMetalContext.bufferCache addObject:indexBuffer];
+                }
             }
         });
     }];
@@ -440,28 +445,31 @@
 {
     uint64_t now = GetMachAbsoluteTimeInSeconds();
 
-    // Purge old buffers that haven't been useful for a while
-    if (now - self.lastBufferCachePurge > 1.0)
+    @synchronized(self.bufferCache)
     {
-        NSMutableArray* survivors = [NSMutableArray array];
+        // Purge old buffers that haven't been useful for a while
+        if (now - self.lastBufferCachePurge > 1.0)
+        {
+            NSMutableArray* survivors = [NSMutableArray array];
+            for (MetalBuffer* candidate in self.bufferCache)
+                if (candidate.lastReuseTime > self.lastBufferCachePurge)
+                    [survivors addObject:candidate];
+            self.bufferCache = [survivors mutableCopy];
+            self.lastBufferCachePurge = now;
+        }
+
+        // See if we have a buffer we can reuse
+        MetalBuffer* bestCandidate = nil;
         for (MetalBuffer* candidate in self.bufferCache)
-            if (candidate.lastReuseTime > self.lastBufferCachePurge)
-                [survivors addObject:candidate];
-        self.bufferCache = [survivors mutableCopy];
-        self.lastBufferCachePurge = now;
-    }
+            if (candidate.buffer.length >= length && (bestCandidate == nil || bestCandidate.lastReuseTime > candidate.lastReuseTime))
+                bestCandidate = candidate;
 
-    // See if we have a buffer we can reuse
-    MetalBuffer* bestCandidate = nil;
-    for (MetalBuffer* candidate in self.bufferCache)
-        if (candidate.buffer.length >= length && (bestCandidate == nil || bestCandidate.lastReuseTime > candidate.lastReuseTime))
-            bestCandidate = candidate;
-
-    if (bestCandidate != nil)
-    {
-        [self.bufferCache removeObject:bestCandidate];
-        bestCandidate.lastReuseTime = now;
-        return bestCandidate;
+        if (bestCandidate != nil)
+        {
+            [self.bufferCache removeObject:bestCandidate];
+            bestCandidate.lastReuseTime = now;
+            return bestCandidate;
+        }
     }
 
     // No luck; make a new buffer
diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index ad3b5ab..0708d8e 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -43,6 +43,7 @@
   Enter keep the input active and select all text.
 - Misc: io.Framerate moving average now converge in 60 frames instead of 120. (#5236, #4138)
 - Backends: Metal: Use __bridge for ARC based systems. (#5403) [@stack]
+- Backends: Metal: Add dispatch synchronization. (#5447) [@luigifcruz]
 - Backends: OSX: Fixes to support full app creation in C++. (#5403) [@stack]