using System;
using System.Collections.Generic;
namespace Barotrauma
{
///
/// Thread-safe queue for deferring physics body creation operations to the main thread.
/// This is necessary because Farseer Physics' DynamicTree is not thread-safe,
/// and physics bodies cannot be safely created during parallel item updates.
///
static class PhysicsBodyQueue
{
private static readonly object _lock = new object();
private static readonly Queue _pendingCreations = new Queue();
///
/// Enqueues a physics body creation action to be executed on the main thread.
/// This method is thread-safe and can be called from parallel update loops.
///
/// The action that creates the physics body
public static void EnqueueCreation(Action createAction)
{
if (createAction == null) { return; }
lock (_lock)
{
_pendingCreations.Enqueue(createAction);
}
}
///
/// Gets the number of pending physics body creation operations.
///
public static int PendingCount
{
get
{
lock (_lock)
{
return _pendingCreations.Count;
}
}
}
///
/// Processes all pending physics body creation operations.
/// Must be called on the main thread, outside of any parallel loops.
///
public static void ProcessPendingCreations()
{
while (true)
{
Action action;
lock (_lock)
{
if (_pendingCreations.Count == 0) { break; }
action = _pendingCreations.Dequeue();
}
try
{
action?.Invoke();
}
catch (Exception e)
{
DebugConsole.ThrowError($"Error processing deferred physics body creation: {e.Message}", e);
}
}
}
///
/// Clears all pending physics body creation operations.
/// Should be called when ending a round or cleaning up.
///
public static void Clear()
{
lock (_lock)
{
_pendingCreations.Clear();
}
}
}
}