Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

async_wrap: WIP/Experiment, init/destroy HTTPParser on each use #5573

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 27 additions & 4 deletions src/async-wrap-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,27 @@ namespace node {
inline AsyncWrap::AsyncWrap(Environment* env,
v8::Local<v8::Object> object,
ProviderType provider,
AsyncWrap* parent)
: BaseObject(env, object), bits_(static_cast<uint32_t>(provider) << 1),
AsyncWrap* parent,
bool manageLifecycleEvents)
: BaseObject(env, object), bits_(static_cast<uint32_t>(provider) << 2),
uid_(env->get_async_wrap_uid()) {
if (manageLifecycleEvents) {
bits_ |= 2; // managed_lifecycle() is now true
InitAsyncWrap(env, object, provider, parent);
}
}


inline AsyncWrap::~AsyncWrap() {
if (managed_lifecycle()) {
DestroyAsyncWrap();
}
}

inline void AsyncWrap::InitAsyncWrap(Environment* env,
v8::Local<v8::Object> object,
ProviderType provider,
AsyncWrap* parent) {
CHECK_NE(provider, PROVIDER_NONE);
CHECK_GE(object->InternalFieldCount(), 1);

Expand Down Expand Up @@ -61,7 +79,7 @@ inline AsyncWrap::AsyncWrap(Environment* env,
}


inline AsyncWrap::~AsyncWrap() {
inline void AsyncWrap::DestroyAsyncWrap() {
if (!ran_init_callback())
return;

Expand All @@ -77,13 +95,18 @@ inline AsyncWrap::~AsyncWrap() {
}


inline bool AsyncWrap::managed_lifecycle() const {
return static_cast<bool>(bits_ & 2);
}


inline bool AsyncWrap::ran_init_callback() const {
return static_cast<bool>(bits_ & 1);
}


inline AsyncWrap::ProviderType AsyncWrap::provider_type() const {
return static_cast<ProviderType>(bits_ >> 1);
return static_cast<ProviderType>(bits_ >> 2);
}


Expand Down
10 changes: 9 additions & 1 deletion src/async-wrap.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,21 @@ class AsyncWrap : public BaseObject {
inline AsyncWrap(Environment* env,
v8::Local<v8::Object> object,
ProviderType provider,
AsyncWrap* parent = nullptr);
AsyncWrap* parent = nullptr,
bool manageLifecycleEvents = true);

inline virtual ~AsyncWrap();

inline ProviderType provider_type() const;

inline int64_t get_uid() const;

inline void InitAsyncWrap(Environment* env,
v8::Local<v8::Object> object,
ProviderType provider,
AsyncWrap* parent = nullptr);
inline void DestroyAsyncWrap();

// Only call these within a valid HandleScope.
v8::Local<v8::Value> MakeCallback(const v8::Local<v8::Function> cb,
int argc,
Expand All @@ -73,6 +80,7 @@ class AsyncWrap : public BaseObject {

private:
inline AsyncWrap();
inline bool managed_lifecycle() const;
inline bool ran_init_callback() const;

// When the async hooks init JS function is called from the constructor it is
Expand Down
4 changes: 3 additions & 1 deletion src/node_http_parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ struct StringPtr {
class Parser : public AsyncWrap {
public:
Parser(Environment* env, Local<Object> wrap, enum http_parser_type type)
: AsyncWrap(env, wrap, AsyncWrap::PROVIDER_HTTPPARSER),
: AsyncWrap(env, wrap, AsyncWrap::PROVIDER_HTTPPARSER, nullptr, false),
current_buffer_len_(0),
current_buffer_data_(nullptr) {
Wrap(object(), this);
Expand Down Expand Up @@ -457,6 +457,7 @@ class Parser : public AsyncWrap {
// Should always be called from the same context.
CHECK_EQ(env, parser->env());
parser->Init(type);
parser->InitAsyncWrap(env, args.This(), AsyncWrap::PROVIDER_HTTPPARSER);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would we have some way to access parent at this point, that we could start providing it through the Init?

Presently, if you disable async_wrap, you don't see the HTTPParser come through, because our parent is null. If we could tie it to the parent server, it would respect the rules a bit better.

shrug

}


Expand Down Expand Up @@ -488,6 +489,7 @@ class Parser : public AsyncWrap {

static void Unconsume(const FunctionCallbackInfo<Value>& args) {
Parser* parser = Unwrap<Parser>(args.Holder());
parser->DestroyAsyncWrap();

// Already unconsumed
if (parser->prev_alloc_cb_.is_empty())
Expand Down