feat(runtime): atomically replace collision generations

This commit is contained in:
Erik 2026-08-01 17:33:34 +02:00
parent 99bf1751bb
commit 9b0f59bd1b
21 changed files with 2435 additions and 408 deletions

View file

@ -217,14 +217,34 @@ public sealed class LandblockPresentationPipeline
/// <summary>
/// Cancels retained publication receipts during a generation reset. A
/// collision receipt owns only its private staging world until activation,
/// so cancellation cannot withdraw or partially replace the active world.
/// pre-engine receipt restores its exact prior generation. A receipt that
/// already transferred the engine generation remains retained until its
/// canonical post-engine placement acknowledgement suffix completes; the
/// committed transfer is never rolled back.
/// </summary>
internal void CancelPendingPublications()
internal bool CancelPendingPublications()
{
foreach (PublicationTransaction transaction in _publications.Values)
transaction.PhysicsPublication?.Dispose();
_publications.Clear();
if (_publications.Count == 0)
return true;
LandblockStreamResult[] pending = [.. _publications.Keys];
bool completed = true;
for (int index = 0; index < pending.Length; index++)
{
LandblockStreamResult result = pending[index];
if (!_publications.TryGetValue(
result,
out PublicationTransaction? transaction))
{
continue;
}
bool cancelled = transaction.PhysicsPublication is not { } physics
|| physics.TryCancel();
if (cancelled)
_publications.Remove(result);
else
completed = false;
}
return completed && _publications.Count == 0;
}
public void ResumePublication(LandblockStreamResult result)
@ -247,10 +267,15 @@ public sealed class LandblockPresentationPipeline
return Advance(result, transaction, meter, ensureProgress);
}
public void AdvanceRetirements() => _retirements.Advance();
public void AdvanceRetirements()
{
_retirements.Advance();
}
public void AdvanceRetirements(StreamingWorkMeter meter) =>
public void AdvanceRetirements(StreamingWorkMeter meter)
{
_retirements.Advance(meter);
}
internal void AdvancePriorityRetirement(
uint landblockId,
@ -261,14 +286,26 @@ public sealed class LandblockPresentationPipeline
{
_retirements.BeginFull(landblockId);
if (_retirements.UsesBudgetedSteps)
{
_retirements.Advance();
if (_retirements.IsPending(landblockId)
&& (_physicsPublisher?.CanContinueMutationSynchronously()
?? true))
_retirements.Advance();
}
}
public void BeginNearLayerRetirement(uint landblockId)
{
_retirements.BeginNearLayer(landblockId);
if (_retirements.UsesBudgetedSteps)
{
_retirements.Advance();
if (_retirements.IsPending(landblockId)
&& (_physicsPublisher?.CanContinueMutationSynchronously()
?? true))
_retirements.Advance();
}
}
internal void EnqueueFullRetirement(uint landblockId) =>
@ -754,6 +791,17 @@ public sealed class LandblockPresentationPipeline
{
return new LandblockPublicationAdvance(false, progressed);
}
if (transaction.PhysicsPublication.RuntimeMutationPending)
{
if (meter is not null
|| !_physicsPublisher
.CanContinueMutationSynchronously())
{
return new LandblockPublicationAdvance(
false,
progressed);
}
}
}
while (!transaction.StaticPublication.CompletionCommitted)
{