@@ -91,17 +91,18 @@ void Scheduler::schedule() noexcept {
9191 bool found_ready_reactions = schedule_ready_reactions ();
9292
9393 while (!found_ready_reactions) {
94+ if (!continue_execution_ && !found_ready_reactions) {
95+ // Cleanup and let all workers know that they should terminate.
96+ cleanup_after_tag ();
97+ terminate_all_workers ();
98+ break ;
99+ }
100+
94101 log_.debug () << " call next()" ;
95102 next ();
96103 reaction_queue_pos_ = 0 ;
97104
98105 found_ready_reactions = schedule_ready_reactions ();
99-
100- if (!continue_execution_ && !found_ready_reactions) {
101- // let all workers know that they should terminate
102- terminate_all_workers ();
103- break ;
104- }
105106 }
106107}
107108
@@ -306,7 +307,7 @@ void Scheduler::advance_logical_time_to(const Tag& tag) {
306307 Statistics::increment_processed_events ();
307308}
308309
309- void Scheduler::next () { // NOLINT
310+ void Scheduler::cleanup_after_tag () {
310311 // Notify other environments and let them know that we finished processing the
311312 // current tag
312313 release_current_tag ();
@@ -328,6 +329,11 @@ void Scheduler::next() { // NOLINT
328329 }
329330 vec_ports.clear ();
330331 }
332+ }
333+
334+ void Scheduler::next () { // NOLINT
335+ // First, clean up after the last tag.
336+ cleanup_after_tag ();
331337
332338 {
333339 std::unique_lock<std::mutex> lock{scheduling_mutex_};
@@ -354,8 +360,8 @@ void Scheduler::next() { // NOLINT
354360 log_.debug () << " Shutting down the scheduler" ;
355361 Tag t_next = Tag::from_logical_time (logical_time_).delay ();
356362 if (!event_queue_.empty () && t_next == event_queue_.next_tag ()) {
357- log_.debug () << " Schedule the last round of reactions including all "
358- " termination reactions" ;
363+ log_.debug () << " Trigger the last round of reactions including all "
364+ " shutdown reactions" ;
359365 triggered_actions_ = event_queue_.extract_next_event ();
360366 advance_logical_time_to (t_next);
361367 } else {
@@ -395,6 +401,17 @@ void Scheduler::next() { // NOLINT
395401 continue ;
396402 }
397403
404+ // Stop execution in case we reach the timeout tag. This checks needs to
405+ // be done here, after acquiring the check, as only then we are fully
406+ // commited to executing the tag t_next. Otherwise, we could still get
407+ // earlier events (e.g., from a physical action).
408+ if (t_next == environment_->timeout_tag ()) {
409+ continue_execution_ = false ;
410+ log_.debug () << " Shutting down the scheduler due to timeout" ;
411+ log_.debug () << " Trigger the last round of reactions including all "
412+ " shutdwon reactions" ;
413+ }
414+
398415 // Retrieve all triggered actions at the next tag.
399416 // We do not need to lock mutex_event_queue_ here, as the lock on
400417 // scheduling_mutex_ already ensures that no one can write to the event
0 commit comments