Skip to content

Commit 81e4455

Browse files
committed
Async: Fix expired timers invocation when they're being cancelled
1 parent a882531 commit 81e4455

File tree

2 files changed

+12
-3
lines changed

2 files changed

+12
-3
lines changed

Libraries/Async/Async.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,15 @@ void SC::AsyncEventLoop::Internal::invokeExpiredTimers(Time::HighResolutionCount
582582
submissions.queueBack(*current);
583583
numberOfSubmissions += 1;
584584
}
585+
if (async != nullptr and not async->isActive())
586+
{
587+
// Our "next" timeout to check could have been Cancelled during the callback
588+
// and it could be in the submission queue now.
589+
// It's possible detecting this case by checking the active state.
590+
// In this case it makes sense to re-check the entire active timers list.
591+
async = activeLoopTimeouts.front;
592+
SC_ASSERT_DEBUG(async == nullptr or async->isActive()); // Should not be possible
593+
}
585594
}
586595
}
587596
}

Libraries/Async/Tests/AsyncTestLoopTimeout.inl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ void SC::AsyncTest::loopTimeout()
1111
int timeout2Called = 0;
1212
timeout1.callback = [&](AsyncLoopTimeout::Result& res)
1313
{
14-
SC_TEST_EXPECT(res.getAsync().relativeTimeout.ms == 1);
14+
SC_TEST_EXPECT(res.getAsync().relativeTimeout == 1_ms);
1515
SC_TEST_EXPECT(res.getAsync().isFree());
1616
SC_TEST_EXPECT(not res.getAsync().isActive());
1717
SC_TEST_EXPECT(not res.getAsync().isCancelling());
@@ -27,11 +27,11 @@ void SC::AsyncTest::loopTimeout()
2727
SC_TEST_EXPECT(not res.getAsync().isActive());
2828
res.reactivateRequest(true);
2929
SC_TEST_EXPECT(res.getAsync().isActive());
30-
res.getAsync().relativeTimeout = Time::Milliseconds(1);
30+
res.getAsync().relativeTimeout = 1_ms;
3131
}
3232
timeout2Called++;
3333
};
34-
SC_TEST_EXPECT(timeout2.start(eventLoop, Time::Milliseconds(100)));
34+
SC_TEST_EXPECT(timeout2.start(eventLoop, 100_ms));
3535
SC_TEST_EXPECT(eventLoop.runOnce());
3636
SC_TEST_EXPECT(timeout1Called == 1 and timeout2Called == 0); // timeout1 fires after 1 ms
3737
SC_TEST_EXPECT(eventLoop.runOnce());

0 commit comments

Comments
 (0)