-
Notifications
You must be signed in to change notification settings - Fork 653
Windows: update loop time lazily #1526
base: v1.x
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,14 +33,34 @@ | |
|
||
|
||
void uv_update_time(uv_loop_t* loop) { | ||
uint64_t new_time = uv__hrtime(UV__MILLISEC); | ||
if (new_time > loop->time) { | ||
loop->time = new_time; | ||
} | ||
/* Invalidate the loop time, so that the next invocation of uv__loop_time() | ||
* will actually update it. | ||
*/ | ||
loop->cached_time_is_valid = 0; | ||
} | ||
|
||
void uv__time_forward(uv_loop_t* loop, uint64_t msecs) { | ||
loop->time += msecs; | ||
loop->cached_time += msecs; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Isn't this a bit dangerous? We's need to make sure uv__time_forward is called always after updating the time, right? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The purpose of uv__time_forward is to ensure that when we finish polling with a timeout, the timeout value is reflected in the loop time (because as we saw, GetQueuedCompletionStatus can return a tad early). "the timeout value is reflected in the loop time" is equivalent to saying that the difference between the next time the time is read (with uv__loop_time()) and the last time it was read must be at least 'msecs'. This code satisfies this requirement, because cached_time is the loop time as it was read last. |
||
loop->cached_time_is_valid = 0; | ||
} | ||
|
||
uint64_t uv__loop_time(const uv_loop_t* loop) { | ||
uv_loop_t* mutable_loop; | ||
uint64_t new_time; | ||
if (!loop->cached_time_is_valid) { | ||
new_time = uv__hrtime(UV__MILLISEC); | ||
mutable_loop = (uv_loop_t*) loop; | ||
if (new_time > mutable_loop->cached_time) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How could this happen? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same logic as before this change: because of uv__time_forward(). the current time (new_time) could actually be lower than cached_time, if GetQueuedCompletionStatus returned early. |
||
mutable_loop->cached_time = new_time; | ||
} | ||
mutable_loop->cached_time_is_valid = 1; | ||
} | ||
|
||
return loop->cached_time; | ||
} | ||
|
||
uint64_t uv_now(const uv_loop_t* loop) { | ||
return uv__loop_time(loop); | ||
} | ||
|
||
|
||
|
@@ -104,7 +124,7 @@ int uv_timer_start(uv_timer_t* handle, uv_timer_cb timer_cb, uint64_t timeout, | |
uv_timer_stop(handle); | ||
|
||
handle->timer_cb = timer_cb; | ||
handle->due = get_clamped_due_time(loop->time, timeout); | ||
handle->due = get_clamped_due_time(uv__loop_time(loop), timeout); | ||
handle->repeat = repeat; | ||
uv__handle_start(handle); | ||
|
||
|
@@ -168,7 +188,7 @@ DWORD uv__next_timeout(const uv_loop_t* loop) { | |
*/ | ||
timer = RB_MIN(uv_timer_tree_s, &((uv_loop_t*)loop)->timers); | ||
if (timer) { | ||
delta = timer->due - loop->time; | ||
delta = timer->due - uv__loop_time(loop); | ||
if (delta >= UINT_MAX - 1) { | ||
/* A timeout value of UINT_MAX means infinite, so that's no good. */ | ||
return UINT_MAX - 1; | ||
|
@@ -190,7 +210,7 @@ void uv_process_timers(uv_loop_t* loop) { | |
|
||
/* Call timer callbacks */ | ||
for (timer = RB_MIN(uv_timer_tree_s, &loop->timers); | ||
timer != NULL && timer->due <= loop->time; | ||
timer != NULL && timer->due <= uv__loop_time(loop); | ||
timer = RB_MIN(uv_timer_tree_s, &loop->timers)) { | ||
|
||
uv_timer_stop(timer); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why did you go with 2 attributes instead of a single one like on the first patch?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
He changed the name of the first attribute so it would reflect its purpose better.
cached_time -> time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, before that. The original patch used loop->time and it invalidated it by setting it to 0.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's because in the previous patch we had nuked uv__time_forward, so it was sufficient to set it to 0 to mean 'invalidated'. Then we realized that we needed to bring uv__time_forward back. So we need to store the minimum value for the next readout, even while the cachec time is invalidated.