Skip to content

Commit 4881722

Browse files
Copilotjhugard
andauthored
Fix ios_WaitTimer ceiling rounding and tighten unit test timing assertions
Agent-Logs-Url: https://github.com/microsoft/libHttpClient/sessions/8aa3ddd0-2395-4c1e-b6a0-b407f9877369 Co-authored-by: jhugard <250834+jhugard@users.noreply.github.com>
1 parent a44764f commit 4881722

2 files changed

Lines changed: 13 additions & 6 deletions

File tree

Source/Task/iOS/ios_WaitTimer.mm

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,13 @@ uint64_t DueTimeFromDeadline(Deadline deadline) noexcept
5555
Cancel();
5656

5757
// NSTimer consumes a relative interval, so convert the stored steady-clock
58-
// deadline back into a relative delay right before arming it.
59-
auto timePoint = DeadlineFromDueTime(dueTime) - Clock::now();
60-
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(timePoint);
58+
// deadline back into a relative delay right before arming it. Use ceiling
59+
// rounding so that a sub-millisecond remainder is rounded up rather than
60+
// truncated to zero, and clamp to zero so a past deadline never produces a
61+
// negative interval that would cause a tight re-arm loop.
62+
auto remaining = DeadlineFromDueTime(dueTime) - Clock::now();
63+
auto ms = std::max(std::chrono::milliseconds(0),
64+
std::chrono::ceil<std::chrono::milliseconds>(remaining));
6165

6266
m_timer = [NSTimer scheduledTimerWithTimeInterval:ms.count() / 1000.0
6367
target:m_target

Tests/UnitTests/Tests/TaskQueueTests.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2182,9 +2182,10 @@ DEFINE_TEST_CLASS(TaskQueueTests)
21822182

21832183
VERIFY_IS_TRUE(siblingState.invoked.load(std::memory_order_acquire));
21842184
VERIFY_IS_FALSE(siblingState.canceled.load(std::memory_order_acquire));
2185+
// The sibling delay is 300 ms; allow up to 50 ms of scheduling jitter.
21852186
VERIFY_IS_GREATER_THAN_OR_EQUAL(
21862187
siblingState.firedAtTicks.load(std::memory_order_acquire) - siblingSubmittedAt,
2187-
static_cast<uint64_t>(200));
2188+
static_cast<uint64_t>(250));
21882189

21892190
XTaskQueueTerminate(siblingQueue, false, nullptr, nullptr);
21902191
while (XTaskQueueDispatch(root, XTaskQueuePort::Work, 0))
@@ -2229,6 +2230,7 @@ DEFINE_TEST_CLASS(TaskQueueTests)
22292230
&firstState,
22302231
&CallbackState::Invoke));
22312232

2233+
const uint64_t secondSubmittedAt = GetTickCount64();
22322234
VERIFY_SUCCEEDED(XTaskQueueSubmitDelayedCallback(
22332235
queue,
22342236
XTaskQueuePort::Work,
@@ -2257,8 +2259,9 @@ DEFINE_TEST_CLASS(TaskQueueTests)
22572259
VERIFY_IS_TRUE(XTaskQueueDispatch(queue, XTaskQueuePort::Work, 2000));
22582260
VERIFY_IS_TRUE(secondState.invoked.load(std::memory_order_acquire));
22592261
VERIFY_IS_FALSE(secondState.canceled.load(std::memory_order_acquire));
2262+
// The second delay is 1000 ms; allow up to 100 ms of scheduling jitter.
22602263
VERIFY_IS_GREATER_THAN_OR_EQUAL(
2261-
secondState.firedAtTicks.load(std::memory_order_acquire) - submittedAt,
2262-
static_cast<uint64_t>(600));
2264+
secondState.firedAtTicks.load(std::memory_order_acquire) - secondSubmittedAt,
2265+
static_cast<uint64_t>(900));
22632266
}
22642267
};

0 commit comments

Comments
 (0)