Skip to content

Commit 7571550

Browse files
addaleaxgibfahn
authored andcommitted
src: introduce internal C++ SetImmediate() mechanism
PR-URL: nodejs#17117 Backport-PR-URL: nodejs#18179 Reviewed-By: James M Snell <[email protected]>
1 parent e066706 commit 7571550

File tree

4 files changed

+73
-32
lines changed

4 files changed

+73
-32
lines changed

src/env-inl.h

+7
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,13 @@ Environment::scheduled_immediate_count() {
539539
return scheduled_immediate_count_;
540540
}
541541

542+
void Environment::SetImmediate(native_immediate_callback cb, void* data) {
543+
native_immediate_callbacks_.push_back({ cb, data });
544+
if (scheduled_immediate_count_[0] == 0)
545+
ActivateImmediateCheck();
546+
scheduled_immediate_count_[0] = scheduled_immediate_count_[0] + 1;
547+
}
548+
542549
inline performance::performance_state* Environment::performance_state() {
543550
return performance_state_;
544551
}

src/env.cc

+52
Original file line numberDiff line numberDiff line change
@@ -223,4 +223,56 @@ void Environment::EnvPromiseHook(v8::PromiseHookType type,
223223
}
224224
}
225225

226+
void Environment::RunAndClearNativeImmediates() {
227+
size_t count = native_immediate_callbacks_.size();
228+
if (count > 0) {
229+
std::vector<NativeImmediateCallback> list;
230+
native_immediate_callbacks_.swap(list);
231+
for (const auto& cb : list) {
232+
cb.cb_(this, cb.data_);
233+
}
234+
235+
#ifdef DEBUG
236+
CHECK_GE(scheduled_immediate_count_[0], count);
237+
#endif
238+
scheduled_immediate_count_[0] = scheduled_immediate_count_[0] - count;
239+
}
240+
}
241+
242+
static bool MaybeStopImmediate(Environment* env) {
243+
if (env->scheduled_immediate_count()[0] == 0) {
244+
uv_check_stop(env->immediate_check_handle());
245+
uv_idle_stop(env->immediate_idle_handle());
246+
return true;
247+
}
248+
return false;
249+
}
250+
251+
252+
void Environment::CheckImmediate(uv_check_t* handle) {
253+
Environment* env = Environment::from_immediate_check_handle(handle);
254+
HandleScope scope(env->isolate());
255+
Context::Scope context_scope(env->context());
256+
257+
if (MaybeStopImmediate(env))
258+
return;
259+
260+
env->RunAndClearNativeImmediates();
261+
262+
MakeCallback(env->isolate(),
263+
env->process_object(),
264+
env->immediate_callback_string(),
265+
0,
266+
nullptr,
267+
{0, 0}).ToLocalChecked();
268+
269+
MaybeStopImmediate(env);
270+
}
271+
272+
void Environment::ActivateImmediateCheck() {
273+
uv_check_start(&immediate_check_handle_, CheckImmediate);
274+
// Idle handle is needed only to stop the event loop from blocking in poll.
275+
uv_idle_start(&immediate_idle_handle_, [](uv_idle_t*){ });
276+
}
277+
226278
} // namespace node

src/env.h

+13
Original file line numberDiff line numberDiff line change
@@ -693,6 +693,11 @@ class Environment {
693693
bool RemovePromiseHook(promise_hook_func fn, void* arg);
694694
bool EmitNapiWarning();
695695

696+
typedef void (*native_immediate_callback)(Environment* env, void* data);
697+
inline void SetImmediate(native_immediate_callback cb, void* data);
698+
// This needs to be available for the JS-land setImmediate().
699+
void ActivateImmediateCheck();
700+
696701
private:
697702
inline void ThrowError(v8::Local<v8::Value> (*fun)(v8::Local<v8::String>),
698703
const char* errmsg);
@@ -753,6 +758,14 @@ class Environment {
753758
};
754759
std::vector<PromiseHookCallback> promise_hooks_;
755760

761+
struct NativeImmediateCallback {
762+
native_immediate_callback cb_;
763+
void* data_;
764+
};
765+
std::vector<NativeImmediateCallback> native_immediate_callbacks_;
766+
void RunAndClearNativeImmediates();
767+
static void CheckImmediate(uv_check_t* handle);
768+
756769
static void EnvPromiseHook(v8::PromiseHookType type,
757770
v8::Local<v8::Promise> promise,
758771
v8::Local<v8::Value> parent);

src/node.cc

+1-32
Original file line numberDiff line numberDiff line change
@@ -3265,40 +3265,9 @@ static void DebugEnd(const FunctionCallbackInfo<Value>& args);
32653265

32663266
namespace {
32673267

3268-
bool MaybeStopImmediate(Environment* env) {
3269-
if (env->scheduled_immediate_count()[0] == 0) {
3270-
uv_check_stop(env->immediate_check_handle());
3271-
uv_idle_stop(env->immediate_idle_handle());
3272-
return true;
3273-
}
3274-
return false;
3275-
}
3276-
3277-
void CheckImmediate(uv_check_t* handle) {
3278-
Environment* env = Environment::from_immediate_check_handle(handle);
3279-
HandleScope scope(env->isolate());
3280-
Context::Scope context_scope(env->context());
3281-
3282-
if (MaybeStopImmediate(env))
3283-
return;
3284-
3285-
MakeCallback(env->isolate(),
3286-
env->process_object(),
3287-
env->immediate_callback_string(),
3288-
0,
3289-
nullptr,
3290-
{0, 0}).ToLocalChecked();
3291-
3292-
MaybeStopImmediate(env);
3293-
}
3294-
3295-
32963268
void ActivateImmediateCheck(const FunctionCallbackInfo<Value>& args) {
32973269
Environment* env = Environment::GetCurrent(args);
3298-
uv_check_start(env->immediate_check_handle(), CheckImmediate);
3299-
// Idle handle is needed only to stop the event loop from blocking in poll.
3300-
uv_idle_start(env->immediate_idle_handle(),
3301-
[](uv_idle_t*){ /* do nothing, just keep the loop running */ });
3270+
env->ActivateImmediateCheck();
33023271
}
33033272

33043273

0 commit comments

Comments
 (0)