From bd47272bc918782d49d6254f9960dad4a34dc6e0 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Sat, 18 Nov 2017 14:24:04 +0100 Subject: [PATCH] src: introduce internal C++ SetImmediate() mechanism Backport-PR-URL: https://github.com/nodejs/node/pull/18179 PR-URL: https://github.com/nodejs/node/pull/17117 Reviewed-By: James M Snell --- src/env-inl.h | 7 +++++++ src/env.cc | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/env.h | 13 +++++++++++++ src/node.cc | 33 +------------------------------- 4 files changed, 73 insertions(+), 32 deletions(-) diff --git a/src/env-inl.h b/src/env-inl.h index 66c677dd6ebccf..90297361cf63bc 100644 --- a/src/env-inl.h +++ b/src/env-inl.h @@ -539,6 +539,13 @@ Environment::scheduled_immediate_count() { return scheduled_immediate_count_; } +void Environment::SetImmediate(native_immediate_callback cb, void* data) { + native_immediate_callbacks_.push_back({ cb, data }); + if (scheduled_immediate_count_[0] == 0) + ActivateImmediateCheck(); + scheduled_immediate_count_[0] = scheduled_immediate_count_[0] + 1; +} + inline performance::performance_state* Environment::performance_state() { return performance_state_; } diff --git a/src/env.cc b/src/env.cc index c46f02dd0ec52f..8899fe987ccd02 100644 --- a/src/env.cc +++ b/src/env.cc @@ -223,4 +223,56 @@ void Environment::EnvPromiseHook(v8::PromiseHookType type, } } +void Environment::RunAndClearNativeImmediates() { + size_t count = native_immediate_callbacks_.size(); + if (count > 0) { + std::vector list; + native_immediate_callbacks_.swap(list); + for (const auto& cb : list) { + cb.cb_(this, cb.data_); + } + +#ifdef DEBUG + CHECK_GE(scheduled_immediate_count_[0], count); +#endif + scheduled_immediate_count_[0] = scheduled_immediate_count_[0] - count; + } +} + +static bool MaybeStopImmediate(Environment* env) { + if (env->scheduled_immediate_count()[0] == 0) { + uv_check_stop(env->immediate_check_handle()); + uv_idle_stop(env->immediate_idle_handle()); + return true; + } + return false; +} + + +void Environment::CheckImmediate(uv_check_t* handle) { + Environment* env = Environment::from_immediate_check_handle(handle); + HandleScope scope(env->isolate()); + Context::Scope context_scope(env->context()); + + if (MaybeStopImmediate(env)) + return; + + env->RunAndClearNativeImmediates(); + + MakeCallback(env->isolate(), + env->process_object(), + env->immediate_callback_string(), + 0, + nullptr, + {0, 0}).ToLocalChecked(); + + MaybeStopImmediate(env); +} + +void Environment::ActivateImmediateCheck() { + uv_check_start(&immediate_check_handle_, CheckImmediate); + // Idle handle is needed only to stop the event loop from blocking in poll. + uv_idle_start(&immediate_idle_handle_, [](uv_idle_t*){ }); +} + } // namespace node diff --git a/src/env.h b/src/env.h index ac5ed89a5a7ba8..80be909442b2dd 100644 --- a/src/env.h +++ b/src/env.h @@ -693,6 +693,11 @@ class Environment { bool RemovePromiseHook(promise_hook_func fn, void* arg); bool EmitNapiWarning(); + typedef void (*native_immediate_callback)(Environment* env, void* data); + inline void SetImmediate(native_immediate_callback cb, void* data); + // This needs to be available for the JS-land setImmediate(). + void ActivateImmediateCheck(); + private: inline void ThrowError(v8::Local (*fun)(v8::Local), const char* errmsg); @@ -753,6 +758,14 @@ class Environment { }; std::vector promise_hooks_; + struct NativeImmediateCallback { + native_immediate_callback cb_; + void* data_; + }; + std::vector native_immediate_callbacks_; + void RunAndClearNativeImmediates(); + static void CheckImmediate(uv_check_t* handle); + static void EnvPromiseHook(v8::PromiseHookType type, v8::Local promise, v8::Local parent); diff --git a/src/node.cc b/src/node.cc index 7d8d9bdc424ea1..e37f8bae72c409 100644 --- a/src/node.cc +++ b/src/node.cc @@ -3265,40 +3265,9 @@ static void DebugEnd(const FunctionCallbackInfo& args); namespace { -bool MaybeStopImmediate(Environment* env) { - if (env->scheduled_immediate_count()[0] == 0) { - uv_check_stop(env->immediate_check_handle()); - uv_idle_stop(env->immediate_idle_handle()); - return true; - } - return false; -} - -void CheckImmediate(uv_check_t* handle) { - Environment* env = Environment::from_immediate_check_handle(handle); - HandleScope scope(env->isolate()); - Context::Scope context_scope(env->context()); - - if (MaybeStopImmediate(env)) - return; - - MakeCallback(env->isolate(), - env->process_object(), - env->immediate_callback_string(), - 0, - nullptr, - {0, 0}).ToLocalChecked(); - - MaybeStopImmediate(env); -} - - void ActivateImmediateCheck(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); - uv_check_start(env->immediate_check_handle(), CheckImmediate); - // Idle handle is needed only to stop the event loop from blocking in poll. - uv_idle_start(env->immediate_idle_handle(), - [](uv_idle_t*){ /* do nothing, just keep the loop running */ }); + env->ActivateImmediateCheck(); }