Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnna Henningsen <anna@addaleax.net>2019-07-15 23:17:45 +0300
committerAnna Henningsen <anna@addaleax.net>2019-08-01 01:51:43 +0300
commit5207dec0175de92116262e8382d6ac57def3a203 (patch)
treee90e855f7a8a228e00fe0d49fb311b319de74c3d /src/env.cc
parent61f3a5c60ad78506e9e0caae061a04ccab878ca1 (diff)
src: allow generic C++ callables in SetImmediate()
Modify the native `SetImmediate()` functions to take generic C++ callables as arguments. This makes passing arguments to the callback easier, and in particular, it allows passing `std::unique_ptr`s directly, which in turn makes sure that the data they point to is deleted if the `Environment` is torn down before the callback can run. PR-URL: https://github.com/nodejs/node/pull/28704 Reviewed-By: James M Snell <jasnell@gmail.com>
Diffstat (limited to 'src/env.cc')
-rw-r--r--src/env.cc66
1 files changed, 31 insertions, 35 deletions
diff --git a/src/env.cc b/src/env.cc
index f0ac855e3d8..ca5e11ac558 100644
--- a/src/env.cc
+++ b/src/env.cc
@@ -339,7 +339,7 @@ Environment::Environment(IsolateData* isolate_data,
[](void* arg) {
Environment* env = static_cast<Environment*>(arg);
if (!env->destroy_async_id_list()->empty())
- AsyncWrap::DestroyAsyncIdsCallback(env, nullptr);
+ AsyncWrap::DestroyAsyncIdsCallback(env);
},
this);
@@ -642,42 +642,38 @@ void Environment::AtExit(void (*cb)(void* arg), void* arg) {
void Environment::RunAndClearNativeImmediates() {
TraceEventScope trace_scope(TRACING_CATEGORY_NODE1(environment),
"RunAndClearNativeImmediates", this);
- size_t count = native_immediate_callbacks_.size();
- if (count > 0) {
- size_t ref_count = 0;
- std::vector<NativeImmediateCallback> list;
- native_immediate_callbacks_.swap(list);
- auto drain_list = [&]() {
- TryCatchScope try_catch(this);
- for (auto it = list.begin(); it != list.end(); ++it) {
- DebugSealHandleScope seal_handle_scope(isolate());
- it->cb_(this, it->data_);
- if (it->refed_)
- ref_count++;
- if (UNLIKELY(try_catch.HasCaught())) {
- if (!try_catch.HasTerminated())
- errors::TriggerUncaughtException(isolate(), try_catch);
-
- // We are done with the current callback. Increase the counter so that
- // the steps below make everything *after* the current item part of
- // the new list.
- it++;
-
- // Bail out, remove the already executed callbacks from list
- // and set up a new TryCatch for the other pending callbacks.
- std::move_backward(it, list.end(), list.begin() + (list.end() - it));
- list.resize(list.end() - it);
- return true;
- }
+ size_t ref_count = 0;
+ size_t count = 0;
+ std::unique_ptr<NativeImmediateCallback> head;
+ head.swap(native_immediate_callbacks_head_);
+ native_immediate_callbacks_tail_ = nullptr;
+
+ auto drain_list = [&]() {
+ TryCatchScope try_catch(this);
+ for (; head; head = head->get_next()) {
+ DebugSealHandleScope seal_handle_scope(isolate());
+ count++;
+ if (head->is_refed())
+ ref_count++;
+
+ head->Call(this);
+ if (UNLIKELY(try_catch.HasCaught())) {
+ if (!try_catch.HasTerminated())
+ errors::TriggerUncaughtException(isolate(), try_catch);
+
+ // We are done with the current callback. Move one iteration along,
+ // as if we had completed successfully.
+ head = head->get_next();
+ return true;
}
- return false;
- };
- while (drain_list()) {}
+ }
+ return false;
+ };
+ while (head && drain_list()) {}
- DCHECK_GE(immediate_info()->count(), count);
- immediate_info()->count_dec(count);
- immediate_info()->ref_count_dec(ref_count);
- }
+ DCHECK_GE(immediate_info()->count(), count);
+ immediate_info()->count_dec(count);
+ immediate_info()->ref_count_dec(ref_count);
}