Skip to content

Commit 4155f0e

Browse files
committed
async_wrap: add uid to TickObject instances
So that each nextTick callback is treated as its own asynchronous event, add a unique id to new TickObject instances. This is a preliminary for allowing the async wrap callbacks to run with nextTick callbacks.
1 parent b11d031 commit 4155f0e

File tree

6 files changed

+63
-7
lines changed

6 files changed

+63
-7
lines changed

lib/internal/async_wrap.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
'use strict';
2+
3+
const async_wrap = process.binding('async_wrap');
4+
const uidArray = async_wrap.getUidArray();
5+
6+
module.exports.getUid =
7+
process.binding('os').isBigEndian ? getUidBE : getUidLE;
8+
9+
10+
function getUidLE() {
11+
if (uidArray[0] === 0xffffffff) {
12+
uidArray[0] = 0;
13+
uidArray[1]++;
14+
}
15+
return uidArray[0] + uidArray[1] * 0x100000000;
16+
}
17+
18+
function getUidBE() {
19+
if (uidArray[1] === 0xffffffff) {
20+
uidArray[1] = 0;
21+
uidArray[0]++;
22+
}
23+
return uidArray[1] + uidArray[0] * 0x100000000;
24+
}

lib/internal/process/next_tick.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
exports.setup = setupNextTick;
44

55
function setupNextTick() {
6+
const async_wrap = require('internal/async_wrap');
67
const promises = require('internal/process/promises');
78
const emitPendingUnhandledRejections = promises.setup(scheduleMicrotasks);
89
var nextTickQueue = [];
@@ -135,6 +136,7 @@ function setupNextTick() {
135136
this.callback = c;
136137
this.domain = process.domain || null;
137138
this.args = args;
139+
this.uid = async_wrap.getUid();
138140
}
139141

140142
function nextTick(callback) {

node.gyp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
'lib/v8.js',
7171
'lib/vm.js',
7272
'lib/zlib.js',
73+
'lib/internal/async_wrap.js',
7374
'lib/internal/child_process.js',
7475
'lib/internal/cluster.js',
7576
'lib/internal/freelist.js',

src/async-wrap.cc

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,13 +156,20 @@ static void SetupHooks(const FunctionCallbackInfo<Value>& args) {
156156
}
157157

158158

159+
static void GetUidArray(const FunctionCallbackInfo<Value>& args) {
160+
Environment* env = Environment::GetCurrent(args);
161+
args.GetReturnValue().Set(env->async_hooks()->get_uid_array());
162+
}
163+
164+
159165
static void Initialize(Local<Object> target,
160-
Local<Value> unused,
161-
Local<Context> context) {
166+
Local<Value> unused,
167+
Local<Context> context) {
162168
Environment* env = Environment::GetCurrent(context);
163169
Isolate* isolate = env->isolate();
164170
HandleScope scope(isolate);
165171

172+
env->SetMethod(target, "getUidArray", GetUidArray);
166173
env->SetMethod(target, "setupHooks", SetupHooks);
167174
env->SetMethod(target, "disable", DisableHooksJS);
168175
env->SetMethod(target, "enable", EnableHooksJS);

src/env-inl.h

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,18 @@ inline v8::Isolate* Environment::IsolateData::isolate() const {
8181
return isolate_;
8282
}
8383

84-
inline Environment::AsyncHooks::AsyncHooks() {
84+
inline Environment::AsyncHooks::AsyncHooks(Environment* env)
85+
: async_wrap_uid_(0),
86+
env_(env) {
8587
for (int i = 0; i < kFieldsCount; i++) fields_[i] = 0;
88+
const size_t array_length = sizeof(async_wrap_uid_) / sizeof(int32_t);
89+
static_assert(array_length == 2, "async_wrap_uid_ unexpected size");
90+
v8::HandleScope handle_scope(env_->isolate());
91+
v8::Local<v8::ArrayBuffer> ab =
92+
v8::ArrayBuffer::New(env_->isolate(), &async_wrap_uid_, array_length);
93+
v8::Local<v8::Uint32Array> ua =
94+
v8::Uint32Array::New(ab, 0, array_length);
95+
async_wrap_uid_array_.Reset(env_->isolate(), ua);
8696
}
8797

8898
inline uint32_t* Environment::AsyncHooks::fields() {
@@ -101,6 +111,14 @@ inline void Environment::AsyncHooks::set_enable_callbacks(uint32_t flag) {
101111
fields_[kEnableCallbacks] = flag;
102112
}
103113

114+
inline int64_t Environment::AsyncHooks::get_async_wrap_uid() {
115+
return ++async_wrap_uid_;
116+
}
117+
118+
inline v8::Local<v8::Uint32Array> Environment::AsyncHooks::get_uid_array() {
119+
return async_wrap_uid_array_.Get(env_->isolate());
120+
}
121+
104122
inline Environment::AsyncCallbackScope::AsyncCallbackScope(Environment* env)
105123
: env_(env) {
106124
env_->makecallback_cntr_++;
@@ -216,12 +234,12 @@ inline Environment::Environment(v8::Local<v8::Context> context,
216234
uv_loop_t* loop)
217235
: isolate_(context->GetIsolate()),
218236
isolate_data_(IsolateData::GetOrCreate(context->GetIsolate(), loop)),
237+
async_hooks_(this),
219238
timer_base_(uv_now(loop)),
220239
using_domains_(false),
221240
printed_error_(false),
222241
trace_sync_io_(false),
223242
makecallback_cntr_(0),
224-
async_wrap_uid_(0),
225243
debugger_agent_(this),
226244
http_parser_buffer_(nullptr),
227245
context_(context->GetIsolate(), context) {
@@ -373,7 +391,7 @@ inline void Environment::set_trace_sync_io(bool value) {
373391
}
374392

375393
inline int64_t Environment::get_async_wrap_uid() {
376-
return ++async_wrap_uid_;
394+
return async_hooks()->get_async_wrap_uid();
377395
}
378396

379397
inline uint32_t* Environment::heap_statistics_buffer() const {

src/env.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -300,10 +300,13 @@ class Environment {
300300
inline int fields_count() const;
301301
inline bool callbacks_enabled();
302302
inline void set_enable_callbacks(uint32_t flag);
303+
inline int64_t get_async_wrap_uid();
304+
inline v8::Local<v8::Uint32Array> get_uid_array();
303305

304306
private:
305307
friend class Environment; // So we can call the constructor.
306-
inline AsyncHooks();
308+
inline AsyncHooks(Environment* env);
309+
v8::Persistent<v8::Uint32Array> async_wrap_uid_array_;
307310

308311
enum Fields {
309312
// Set this to not zero if the init hook should be called.
@@ -312,6 +315,8 @@ class Environment {
312315
};
313316

314317
uint32_t fields_[kFieldsCount];
318+
int64_t async_wrap_uid_;
319+
Environment* env_;
315320

316321
DISALLOW_COPY_AND_ASSIGN(AsyncHooks);
317322
};
@@ -577,7 +582,6 @@ class Environment {
577582
bool printed_error_;
578583
bool trace_sync_io_;
579584
size_t makecallback_cntr_;
580-
int64_t async_wrap_uid_;
581585
debugger::Agent debugger_agent_;
582586

583587
HandleWrapQueue handle_wrap_queue_;

0 commit comments

Comments
 (0)