diff options
author | Bartek IwaĆczuk <biwanczuk@gmail.com> | 2020-09-20 01:17:35 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-09-20 01:17:35 +0200 |
commit | b657d743a22802b8232fbf558f2f00bf2942096f (patch) | |
tree | e3a3047e78b6bd9c9e3f551f99f5e80e32de079d /cli/ops/timers.rs | |
parent | aaa5e6613a739f8e2ff7579b69c2504bcdc37d4f (diff) |
refactor: remove CliState, use OpState, add CliModuleLoader (#7588)
- remove "CliState.workers" and "CliState.next_worker_id", instead
store them on "OpState" using type aliases.
- remove "CliState.global_timer" and "CliState.start_time", instead
store them on "OpState" using type aliases.
- remove "CliState.is_internal", instead pass it to Worker::new
- move "CliState::permissions" to "OpState"
- move "CliState::main_module" to "OpState"
- move "CliState::global_state" to "OpState"
- move "CliState::check_unstable()" to "GlobalState"
- change "cli_state()" to "global_state()"
- change "deno_core::ModuleLoader" trait to pass "OpState" to callbacks
- rename "CliState" to "CliModuleLoader"
Diffstat (limited to 'cli/ops/timers.rs')
-rw-r--r-- | cli/ops/timers.rs | 56 |
1 files changed, 50 insertions, 6 deletions
diff --git a/cli/ops/timers.rs b/cli/ops/timers.rs index e52bb5b0e..a3aef3fef 100644 --- a/cli/ops/timers.rs +++ b/cli/ops/timers.rs @@ -1,17 +1,61 @@ // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. -use crate::global_timer::GlobalTimer; +//! This module helps deno implement timers. +//! +//! As an optimization, we want to avoid an expensive calls into rust for every +//! setTimeout in JavaScript. Thus in //js/timers.ts a data structure is +//! implemented that calls into Rust for only the smallest timeout. Thus we +//! only need to be able to start and cancel a single timer (or Delay, as Tokio +//! calls it) for an entire Isolate. This is what is implemented here. + +use crate::permissions::Permissions; use deno_core::error::AnyError; use deno_core::BufVec; use deno_core::OpState; use deno_core::ZeroCopyBuf; -use futures::future::FutureExt; +use futures::channel::oneshot; +use futures::FutureExt; +use futures::TryFutureExt; use serde::Deserialize; use serde_json::Value; use std::cell::RefCell; +use std::future::Future; use std::rc::Rc; use std::time::Duration; use std::time::Instant; +pub type StartTime = Instant; + +#[derive(Default)] +pub struct GlobalTimer { + tx: Option<oneshot::Sender<()>>, +} + +impl GlobalTimer { + pub fn cancel(&mut self) { + if let Some(tx) = self.tx.take() { + tx.send(()).ok(); + } + } + + pub fn new_timeout( + &mut self, + deadline: Instant, + ) -> impl Future<Output = Result<(), ()>> { + if self.tx.is_some() { + self.cancel(); + } + assert!(self.tx.is_none()); + + let (tx, rx) = oneshot::channel(); + self.tx = Some(tx); + + let delay = tokio::time::delay_until(deadline.into()); + let rx = rx + .map_err(|err| panic!("Unexpected error in receiving channel {:?}", err)); + + futures::future::select(delay, rx).then(|_| futures::future::ok(())) + } +} pub fn init(rt: &mut deno_core::JsRuntime) { super::reg_json_sync(rt, "op_global_timer_stop", op_global_timer_stop); @@ -61,15 +105,15 @@ fn op_now( _args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result<Value, AnyError> { - let cli_state = super::cli_state(state); - let seconds = cli_state.start_time.elapsed().as_secs(); - let mut subsec_nanos = cli_state.start_time.elapsed().subsec_nanos(); + let start_time = state.borrow::<StartTime>(); + let seconds = start_time.elapsed().as_secs(); + let mut subsec_nanos = start_time.elapsed().subsec_nanos(); let reduced_time_precision = 2_000_000; // 2ms in nanoseconds // If the permission is not enabled // Round the nano result on 2 milliseconds // see: https://developer.mozilla.org/en-US/docs/Web/API/DOMHighResTimeStamp#Reduced_time_precision - if cli_state.check_hrtime().is_err() { + if state.borrow::<Permissions>().check_hrtime().is_err() { subsec_nanos -= subsec_nanos % reduced_time_precision; } |