Skip to content

Commit cad1a62

Browse files
committedApr 27, 2016
src: use libuv's refcounting directly
Don't implement an additional reference counting scheme on top of libuv. Libuv is the canonical source for that information so use it directly. PR-URL: #6395 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: James M Snell <[email protected]>
1 parent 23818c6 commit cad1a62

File tree

3 files changed

+30
-31
lines changed

3 files changed

+30
-31
lines changed
 

‎src/handle_wrap.cc

+18-24
Original file line numberDiff line numberDiff line change
@@ -20,28 +20,25 @@ using v8::Value;
2020
void HandleWrap::Ref(const FunctionCallbackInfo<Value>& args) {
2121
HandleWrap* wrap = Unwrap<HandleWrap>(args.Holder());
2222

23-
if (IsAlive(wrap)) {
24-
uv_ref(wrap->handle__);
25-
wrap->flags_ &= ~kUnref;
26-
}
23+
if (IsAlive(wrap))
24+
uv_ref(wrap->GetHandle());
2725
}
2826

2927

3028
void HandleWrap::Unref(const FunctionCallbackInfo<Value>& args) {
3129
HandleWrap* wrap = Unwrap<HandleWrap>(args.Holder());
3230

33-
if (IsAlive(wrap)) {
34-
uv_unref(wrap->handle__);
35-
wrap->flags_ |= kUnref;
36-
}
31+
if (IsAlive(wrap))
32+
uv_unref(wrap->GetHandle());
3733
}
3834

3935

4036
void HandleWrap::Unrefed(const FunctionCallbackInfo<Value>& args) {
4137
HandleWrap* wrap = Unwrap<HandleWrap>(args.Holder());
42-
43-
bool unrefed = wrap->flags_ & kUnref == 1;
44-
args.GetReturnValue().Set(unrefed);
38+
// XXX(bnoordhuis) It's debatable whether a nullptr wrap should count
39+
// as having a reference count but it's compatible with the logic that
40+
// it replaces.
41+
args.GetReturnValue().Set(wrap == nullptr || !HasRef(wrap));
4542
}
4643

4744

@@ -50,17 +47,17 @@ void HandleWrap::Close(const FunctionCallbackInfo<Value>& args) {
5047

5148
HandleWrap* wrap = Unwrap<HandleWrap>(args.Holder());
5249

53-
// guard against uninitialized handle or double close
50+
// Guard against uninitialized handle or double close.
5451
if (!IsAlive(wrap))
5552
return;
5653

5754
CHECK_EQ(false, wrap->persistent().IsEmpty());
5855
uv_close(wrap->handle__, OnClose);
59-
wrap->handle__ = nullptr;
56+
wrap->state_ = kClosing;
6057

6158
if (args[0]->IsFunction()) {
6259
wrap->object()->Set(env->onclose_string(), args[0]);
63-
wrap->flags_ |= kCloseCallback;
60+
wrap->state_ = kClosingWithCallback;
6461
}
6562
}
6663

@@ -71,7 +68,7 @@ HandleWrap::HandleWrap(Environment* env,
7168
AsyncWrap::ProviderType provider,
7269
AsyncWrap* parent)
7370
: AsyncWrap(env, object, provider, parent),
74-
flags_(0),
71+
state_(kInitialized),
7572
handle__(handle) {
7673
handle__->data = this;
7774
HandleScope scope(env->isolate());
@@ -89,22 +86,19 @@ void HandleWrap::OnClose(uv_handle_t* handle) {
8986
HandleWrap* wrap = static_cast<HandleWrap*>(handle->data);
9087
Environment* env = wrap->env();
9188
HandleScope scope(env->isolate());
89+
Context::Scope context_scope(env->context());
9290

9391
// The wrap object should still be there.
9492
CHECK_EQ(wrap->persistent().IsEmpty(), false);
93+
CHECK(wrap->state_ >= kClosing && wrap->state_ <= kClosingWithCallback);
9594

96-
// But the handle pointer should be gone.
97-
CHECK_EQ(wrap->handle__, nullptr);
95+
const bool have_close_callback = (wrap->state_ == kClosingWithCallback);
96+
wrap->state_ = kClosed;
9897

99-
HandleScope handle_scope(env->isolate());
100-
Context::Scope context_scope(env->context());
101-
Local<Object> object = wrap->object();
102-
103-
if (wrap->flags_ & kCloseCallback) {
98+
if (have_close_callback)
10499
wrap->MakeCallback(env->onclose_string(), 0, nullptr);
105-
}
106100

107-
object->SetAlignedPointerInInternalField(0, nullptr);
101+
wrap->object()->SetAlignedPointerInInternalField(0, nullptr);
108102
wrap->persistent().Reset();
109103
delete wrap;
110104
}

‎src/handle_wrap.h

+11-6
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,15 @@ class HandleWrap : public AsyncWrap {
3838
static void Unrefed(const v8::FunctionCallbackInfo<v8::Value>& args);
3939

4040
static inline bool IsAlive(const HandleWrap* wrap) {
41-
return wrap != nullptr && wrap->GetHandle() != nullptr;
41+
// XXX(bnoordhuis) It's debatable whether only kInitialized should
42+
// count as alive but it's compatible with the check that it replaces.
43+
return wrap != nullptr && wrap->state_ == kInitialized;
44+
}
45+
46+
static inline bool HasRef(const HandleWrap* wrap) {
47+
return wrap != nullptr &&
48+
wrap->state_ != kClosed &&
49+
uv_has_ref(wrap->GetHandle());
4250
}
4351

4452
inline uv_handle_t* GetHandle() const { return handle__; }
@@ -56,13 +64,10 @@ class HandleWrap : public AsyncWrap {
5664
friend void GetActiveHandles(const v8::FunctionCallbackInfo<v8::Value>&);
5765
static void OnClose(uv_handle_t* handle);
5866
ListNode<HandleWrap> handle_wrap_queue_;
59-
unsigned int flags_;
67+
enum { kInitialized, kClosing, kClosingWithCallback, kClosed } state_;
6068
// Using double underscore due to handle_ member in tcp_wrap. Probably
6169
// tcp_wrap should rename it's member to 'handle'.
62-
uv_handle_t* handle__;
63-
64-
static const unsigned int kUnref = 1;
65-
static const unsigned int kCloseCallback = 2;
70+
uv_handle_t* const handle__;
6671
};
6772

6873

‎src/node.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -1723,7 +1723,7 @@ void GetActiveHandles(const FunctionCallbackInfo<Value>& args) {
17231723
Local<String> owner_sym = env->owner_string();
17241724

17251725
for (auto w : *env->handle_wrap_queue()) {
1726-
if (w->persistent().IsEmpty() || (w->flags_ & HandleWrap::kUnref))
1726+
if (w->persistent().IsEmpty() || !HandleWrap::HasRef(w))
17271727
continue;
17281728
Local<Object> object = w->object();
17291729
Local<Value> owner = object->Get(owner_sym);

0 commit comments

Comments
 (0)
Please sign in to comment.