-
Notifications
You must be signed in to change notification settings - Fork 5.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
First pass at setTimeout with Tokio #434
Conversation
@@ -76,13 +83,20 @@ export function setInterval( | |||
// tslint:disable-next-line:no-any | |||
...args: any[] | |||
): number { |
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.
I realize it's not from the Tokio stuff but was also the case before - but Is there any reason you prefer returning numbers from timers and not objects like Node does? Do you think the .unref
stuff is not a concern/not interesting?
(Not related to the comments about maybe returning promises - which might not be 100% compatible but is certainly how it would have been done if they did these APIs today)
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 reason - actually I thought it was the spec.
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.
@ry well, I help maintain lolex so I dug into this quite a bit at times.
- browsers "implement" the Timers spec - I say "implement" because browsers vary a lot between themselves in how they handle overflow and timer behaviour for edge cases.
- Node doesn't implement that spec at all and returns objects from timers to expose optimizations.
- Other platforms that run JavaScript don't do this or vary.
I think timer libs already expect either Node or browser timers mostly - we get some wiggle room - the important thing (other than timer ordering) is that setTimeout
returns an object that clearTimeout
clears.
build_extra/rust/BUILD.gn
Outdated
extern = [ ":libc" ] | ||
} | ||
|
||
tokio_root = "/Users/rld/src/deno/third_party/rust_crates/git/checkouts/tokio-377c595163f99a10/5d0d2a2/" |
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.
tokio_root = "$crates/git/checkouts/tokio-377c595163f99a10/5d0d2a2/"
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.
oops :)
dc10a26
to
61d5e4a
Compare
5badb98
to
7556f14
Compare
src/handlers.rs
Outdated
@@ -212,6 +212,10 @@ where | |||
} | |||
|
|||
fn send_timer_ready(d: *const DenoC, cmd_id: u32, timer_id: u32, done: bool) { | |||
// Remove the cancel from the timers table. | |||
let deno = from_c(d); | |||
deno.timers.remove(&timer_id); |
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.
This will remove the ability to clear a running interval.
deno.rt.spawn(interval_task); | ||
} else { | ||
let (delay_task, cancel_delay) = set_timeout( | ||
move || { |
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.
Should be here
let (delay_task, cancel_delay) = set_timeout(
move || {
send_timer_ready(d, cmd_id, timer_id, true);
let deno = from_c(d);
deno.timers.remove(&timer_id);
},
delay,
);
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.
done - albeit in a hacky way. (thanks!)
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.
Almost. remove_timer
needs to be called from the delay task, not the interval task.
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.
oops - thanks!
ebed252
to
ccedaab
Compare
cd77dd3
to
b54ae27
Compare
b8d1337
to
b54ae27
Compare
Still working on getting winapi-0.3 and 0.3 to coexist. |
@piscisaureus PTAL |
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.
LGTM, please look at the comments.
I must say I am a little nervous about how tightly coupled to Tokio this gets us.
js/globals.ts
Outdated
// window["setInterval"] = timer.setInterval; | ||
// window["clearTimeout"] = timer.clearTimer; | ||
// window["clearInterval"] = timer.clearTimer; | ||
window["setTimeout"] = timers.setTimeout; |
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.
I don't really understand why this needs to be window["foo"]
instead of window.foo
.
If there's reason maybe add a comment? I'm a bit surprised that prettier leaves it as-is.
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.
Fixed.
const { timerReadyId, timerReadyDone } = msg; | ||
export function onMessage(msg: fbs.TimerReady) { | ||
const timerReadyId = msg.id(); | ||
const timerReadyDone = msg.done(); | ||
const timer = timers.get(timerReadyId); | ||
if (!timer) { | ||
return; |
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.
I would really like to see a test that exercises this code path. Maybe something like:
const timers = [];
let timeouts = 0;
for (let i = 0; i < 10; i++) {
timers[i] = setTimeout(onTimeout, 20);
}
function onTimeout() {
++timeouts;
for (let i = 1; i < 10; i++) {
clearTimeout(timers[i]);
}
}
assert(timeouts === 1);
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.
@@ -204,4 +212,7 @@ fn main() { | |||
error!("{}", err); | |||
std::process::exit(1); | |||
}); | |||
|
|||
// Start the Tokio event loop | |||
d.rt.run().expect("err"); |
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.
Ok for now, I think, fingers crossed.
But we'll have to contain this soon or we might as well rename to tokio.js already.
src/handlers.rs
Outdated
F: Fn() -> (), | ||
{ | ||
let (cancel_tx, cancel_rx) = oneshot::channel::<()>(); | ||
let when = Duration::from_millis(delay.into()); |
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.
This is misnamed - when
suggests that this is an absolute time, but the variable actually contains a time delta.
If it had said let when = Instant::now() + Duration::from_millis(delay.into())
it'd be accurate.
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.
Fixed.
Depends on #429
Fixes #413