diff --git a/lib/src/simulator.dart b/lib/src/simulator.dart index 1c99ef27f..ed06ef603 100644 --- a/lib/src/simulator.dart +++ b/lib/src/simulator.dart @@ -56,6 +56,9 @@ class Simulator { /// Functions to be executed as soon as possible by the [Simulator]. static final Queue _injectedActions = Queue(); + /// Functions to be executed at the end of the simulation. + static final Queue _endOfSimulationActions = Queue(); + /// Emits an event before any other actions take place on the tick. static Stream get preTick => _preTickController.stream; @@ -133,6 +136,13 @@ class Simulator { _pendingTimestamps[timestamp]!.add(action); } + /// Registers an arbitrary [action] to be executed at the end of the simulation. + /// + /// The simulation will not be marked as ended until these actions complete. + static void registerEndOfSimulationAction(Function() action) { + _endOfSimulationActions.add(action); + } + /// Adds an arbitrary [action] to be executed as soon as possible, during the current /// simulation tick if possible. /// @@ -218,9 +228,16 @@ class Simulator { (_maxSimTime < 0 || _currentTimestamp < _maxSimTime)) { await tick(); // make this async so that await-ing events works } + if (_currentTimestamp >= _maxSimTime && _maxSimTime > 0) { logger.warning('Simulation ended due to maximum simulation time.'); } + + while (_endOfSimulationActions.isNotEmpty) { + var endOfSimAction = _endOfSimulationActions.removeFirst(); + await endOfSimAction(); + } + _simulationEndedCompleter.complete(); await simulationEnded; } diff --git a/test/simulator_test.dart b/test/simulator_test.dart index 862817992..7ceba00e7 100644 --- a/test/simulator_test.dart +++ b/test/simulator_test.dart @@ -8,6 +8,8 @@ /// Author: Max Korbel /// +import 'dart:async'; + import 'package:rohd/rohd.dart'; import 'package:test/test.dart'; @@ -56,4 +58,25 @@ void main() { Simulator.registerAction(100, () => true); await Simulator.run(); }); + + test('simulator end of action waits before ending', () async { + var endOfSimActionExecuted = false; + Simulator.registerAction(100, () => true); + Simulator.registerEndOfSimulationAction( + () => endOfSimActionExecuted = true); + unawaited(Simulator.simulationEnded + .then((value) => expect(endOfSimActionExecuted, isTrue))); + await Simulator.run(); + }); + + test('simulator end of action waits async before ending', () async { + var endOfSimActionExecuted = false; + Simulator.registerAction(100, () => true); + Simulator.registerEndOfSimulationAction(() async { + await Future.delayed(Duration(microseconds: 10)); + endOfSimActionExecuted = true; + }); + await Simulator.run(); + expect(endOfSimActionExecuted, isTrue); + }); }