src: introduce internal C++ SetImmediate() mechanism
PR-URL: https://github.com/nodejs/node/pull/17117 Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
parent
69e6c5a212
commit
85f3e319c4
@ -492,6 +492,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_;
|
||||
}
|
||||
|
53
src/env.cc
53
src/env.cc
@ -277,6 +277,59 @@ void Environment::EnvPromiseHook(v8::PromiseHookType type,
|
||||
}
|
||||
}
|
||||
|
||||
void Environment::RunAndClearNativeImmediates() {
|
||||
size_t count = native_immediate_callbacks_.size();
|
||||
if (count > 0) {
|
||||
std::vector<NativeImmediateCallback> 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*){ });
|
||||
}
|
||||
|
||||
|
||||
void CollectExceptionInfo(Environment* env,
|
||||
v8::Local<v8::Object> obj,
|
||||
int errorno,
|
||||
|
13
src/env.h
13
src/env.h
@ -688,6 +688,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<v8::Value> (*fun)(v8::Local<v8::String>),
|
||||
const char* errmsg);
|
||||
@ -747,6 +752,14 @@ class Environment {
|
||||
};
|
||||
std::vector<PromiseHookCallback> promise_hooks_;
|
||||
|
||||
struct NativeImmediateCallback {
|
||||
native_immediate_callback cb_;
|
||||
void* data_;
|
||||
};
|
||||
std::vector<NativeImmediateCallback> native_immediate_callbacks_;
|
||||
void RunAndClearNativeImmediates();
|
||||
static void CheckImmediate(uv_check_t* handle);
|
||||
|
||||
static void EnvPromiseHook(v8::PromiseHookType type,
|
||||
v8::Local<v8::Promise> promise,
|
||||
v8::Local<v8::Value> parent);
|
||||
|
33
src/node.cc
33
src/node.cc
@ -2933,40 +2933,9 @@ static void DebugEnd(const FunctionCallbackInfo<Value>& 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<Value>& 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();
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user