Skip to content

Commit e1f0846

Browse files
addaleaxMylesBorins
authored andcommitted
src: introduce internal C++ SetImmediate() mechanism
PR-URL: #17117 Reviewed-By: James M Snell <[email protected]>
1 parent ffe1ad6 commit e1f0846

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
@@ -501,6 +501,13 @@ Environment::scheduled_immediate_count() {
501501
return scheduled_immediate_count_;
502502
}
503503

504+
void Environment::SetImmediate(native_immediate_callback cb, void* data) {
505+
native_immediate_callbacks_.push_back({ cb, data });
506+
if (scheduled_immediate_count_[0] == 0)
507+
ActivateImmediateCheck();
508+
scheduled_immediate_count_[0] = scheduled_immediate_count_[0] + 1;
509+
}
510+
504511
inline performance::performance_state* Environment::performance_state() {
505512
return performance_state_;
506513
}

src/env.cc

+52
Original file line numberDiff line numberDiff line change
@@ -275,4 +275,56 @@ void Environment::EnvPromiseHook(v8::PromiseHookType type,
275275
}
276276
}
277277

278+
void Environment::RunAndClearNativeImmediates() {
279+
size_t count = native_immediate_callbacks_.size();
280+
if (count > 0) {
281+
std::vector<NativeImmediateCallback> list;
282+
native_immediate_callbacks_.swap(list);
283+
for (const auto& cb : list) {
284+
cb.cb_(this, cb.data_);
285+
}
286+
287+
#ifdef DEBUG
288+
CHECK_GE(scheduled_immediate_count_[0], count);
289+
#endif
290+
scheduled_immediate_count_[0] = scheduled_immediate_count_[0] - count;
291+
}
292+
}
293+
294+
static bool MaybeStopImmediate(Environment* env) {
295+
if (env->scheduled_immediate_count()[0] == 0) {
296+
uv_check_stop(env->immediate_check_handle());
297+
uv_idle_stop(env->immediate_idle_handle());
298+
return true;
299+
}
300+
return false;
301+
}
302+
303+
304+
void Environment::CheckImmediate(uv_check_t* handle) {
305+
Environment* env = Environment::from_immediate_check_handle(handle);
306+
HandleScope scope(env->isolate());
307+
Context::Scope context_scope(env->context());
308+
309+
if (MaybeStopImmediate(env))
310+
return;
311+
312+
env->RunAndClearNativeImmediates();
313+
314+
MakeCallback(env->isolate(),
315+
env->process_object(),
316+
env->immediate_callback_string(),
317+
0,
318+
nullptr,
319+
{0, 0}).ToLocalChecked();
320+
321+
MaybeStopImmediate(env);
322+
}
323+
324+
void Environment::ActivateImmediateCheck() {
325+
uv_check_start(&immediate_check_handle_, CheckImmediate);
326+
// Idle handle is needed only to stop the event loop from blocking in poll.
327+
uv_idle_start(&immediate_idle_handle_, [](uv_idle_t*){ });
328+
}
329+
278330
} // namespace node

src/env.h

+13
Original file line numberDiff line numberDiff line change
@@ -680,6 +680,11 @@ class Environment {
680680
bool RemovePromiseHook(promise_hook_func fn, void* arg);
681681
bool EmitNapiWarning();
682682

683+
typedef void (*native_immediate_callback)(Environment* env, void* data);
684+
inline void SetImmediate(native_immediate_callback cb, void* data);
685+
// This needs to be available for the JS-land setImmediate().
686+
void ActivateImmediateCheck();
687+
683688
private:
684689
inline void ThrowError(v8::Local<v8::Value> (*fun)(v8::Local<v8::String>),
685690
const char* errmsg);
@@ -740,6 +745,14 @@ class Environment {
740745
};
741746
std::vector<PromiseHookCallback> promise_hooks_;
742747

748+
struct NativeImmediateCallback {
749+
native_immediate_callback cb_;
750+
void* data_;
751+
};
752+
std::vector<NativeImmediateCallback> native_immediate_callbacks_;
753+
void RunAndClearNativeImmediates();
754+
static void CheckImmediate(uv_check_t* handle);
755+
743756
static void EnvPromiseHook(v8::PromiseHookType type,
744757
v8::Local<v8::Promise> promise,
745758
v8::Local<v8::Value> parent);

src/node.cc

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

32133213
namespace {
32143214

3215-
bool MaybeStopImmediate(Environment* env) {
3216-
if (env->scheduled_immediate_count()[0] == 0) {
3217-
uv_check_stop(env->immediate_check_handle());
3218-
uv_idle_stop(env->immediate_idle_handle());
3219-
return true;
3220-
}
3221-
return false;
3222-
}
3223-
3224-
void CheckImmediate(uv_check_t* handle) {
3225-
Environment* env = Environment::from_immediate_check_handle(handle);
3226-
HandleScope scope(env->isolate());
3227-
Context::Scope context_scope(env->context());
3228-
3229-
if (MaybeStopImmediate(env))
3230-
return;
3231-
3232-
MakeCallback(env->isolate(),
3233-
env->process_object(),
3234-
env->immediate_callback_string(),
3235-
0,
3236-
nullptr,
3237-
{0, 0}).ToLocalChecked();
3238-
3239-
MaybeStopImmediate(env);
3240-
}
3241-
3242-
32433215
void ActivateImmediateCheck(const FunctionCallbackInfo<Value>& args) {
32443216
Environment* env = Environment::GetCurrent(args);
3245-
uv_check_start(env->immediate_check_handle(), CheckImmediate);
3246-
// Idle handle is needed only to stop the event loop from blocking in poll.
3247-
uv_idle_start(env->immediate_idle_handle(),
3248-
[](uv_idle_t*){ /* do nothing, just keep the loop running */ });
3217+
env->ActivateImmediateCheck();
32493218
}
32503219

32513220

0 commit comments

Comments
 (0)