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_;
|
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() {
|
inline performance::performance_state* Environment::performance_state() {
|
||||||
return 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,
|
void CollectExceptionInfo(Environment* env,
|
||||||
v8::Local<v8::Object> obj,
|
v8::Local<v8::Object> obj,
|
||||||
int errorno,
|
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 RemovePromiseHook(promise_hook_func fn, void* arg);
|
||||||
bool EmitNapiWarning();
|
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:
|
private:
|
||||||
inline void ThrowError(v8::Local<v8::Value> (*fun)(v8::Local<v8::String>),
|
inline void ThrowError(v8::Local<v8::Value> (*fun)(v8::Local<v8::String>),
|
||||||
const char* errmsg);
|
const char* errmsg);
|
||||||
@ -747,6 +752,14 @@ class Environment {
|
|||||||
};
|
};
|
||||||
std::vector<PromiseHookCallback> promise_hooks_;
|
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,
|
static void EnvPromiseHook(v8::PromiseHookType type,
|
||||||
v8::Local<v8::Promise> promise,
|
v8::Local<v8::Promise> promise,
|
||||||
v8::Local<v8::Value> parent);
|
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 {
|
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) {
|
void ActivateImmediateCheck(const FunctionCallbackInfo<Value>& args) {
|
||||||
Environment* env = Environment::GetCurrent(args);
|
Environment* env = Environment::GetCurrent(args);
|
||||||
uv_check_start(env->immediate_check_handle(), CheckImmediate);
|
env->ActivateImmediateCheck();
|
||||||
// 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 */ });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user