diff --git a/src/main/java/org/syndicate_lang/actors/Turn.java b/src/main/java/org/syndicate_lang/actors/Turn.java index 691f41b..06e3ecd 100644 --- a/src/main/java/org/syndicate_lang/actors/Turn.java +++ b/src/main/java/org/syndicate_lang/actors/Turn.java @@ -8,7 +8,10 @@ import java.util.logging.Logger; public class Turn { private final static AtomicLong nextHandle = new AtomicLong(0); + private final static record SinglePending(Actor ac, List> actions) {} + private final Actor _actor; + private SinglePending _singlePending = null; private Map>> _pending = null; private boolean _complete = false; @@ -42,13 +45,36 @@ public class Turn { if (_pending != null) { _pending.forEach((ac, q) -> ac.execute(() -> Turn.forActor(ac, t -> q.forEach(f -> f.accept(t))))); _pending = null; + } else if (_singlePending != null) { + var ac = _singlePending.ac(); + var q = _singlePending.actions(); + _singlePending = null; + ac.execute(() -> Turn.forActor(ac, t -> q.forEach(f -> f.accept(t)))); } _complete = true; } + private static LinkedList> singletonList(Consumer action) { + var q = new LinkedList>(); + q.add(action); + return q; + } + private void enqueue(Actor target, Consumer action) { if (_complete) throw new IllegalStateException("Attempt to reuse a committed Turn"); - if (_pending == null) _pending = new HashMap<>(); + if (_pending == null) { + if (_singlePending == null) { + _singlePending = new SinglePending(target, singletonList(action)); + return; + } + if (_singlePending.ac() == target) { + _singlePending.actions().add(action); + return; + } + _pending = new HashMap<>(); + _pending.put(_singlePending.ac(), _singlePending.actions()); + _singlePending = null; + } _pending.computeIfAbsent(target, k -> new LinkedList<>()).add(action); }