Repository navigation
Lifetime of a Buffer in a C++ addon #3222
Description
Activity
You need to either keep a reference around to the buffer object or make a copy of the data. It looks like you're already using a
v8::Persistent<T>orv8::Global<T>for the callback, I'd just extend that to the buffer object.Ahh, yeah, makes sense. So in my class something like:
v8::Persistent<v8::Object> buffer_; v8::Persistent<v8::Function> callback_; // I already have this oneAnd then set it in my function the same way I'm setting the callback:
obj->buffer_.Reset(isolate, args[0]); obj->callback_.Reset(isolate, callback);Am I then correct in assuming that when my class's destructor is called these two persistent references are both released, so there isn't anything else I would need to do?
Now that I know where to look, it seems obvious; I'm guessing that I can also make a call to
buffer_.Reset()(with no arguments) in my class' cleanup function (to force cleanup independent of GC) to release the handles without having to rely on my destructor being called, correct?v8::Persistent<T>doesn't Reset() in its destructor (by default) butv8::Global<T>does. If you want to play it safe, call Reset() explicitly in your destructor.- addedbufferIssues and PRs related to the buffer subsystem.Issues and PRs related to the buffer subsystem.c++Issues and PRs that require attention from people who are familiar with C++.Issues and PRs that require attention from people who are familiar with C++.questionIssues asking questions about Node.js.Issues asking questions about Node.js.
on Oct 6, 2015 Ahh, yep, once again, knowing what to look for helps. For future reference, I found the relevant section in Google's v8 Embedder's Guide: https://developers.google.com/v8/embed#handles-and-garbage-collection
Specifically where they state:
A
Persistent<SomeType>can be constructed with its constructor, but must be explicitly cleared withPersistent::Reset.Thanks for the help!
@bnoordhuis Upon further reading, I found this comment in the same guide:
During the garbage collection process the garbage collector often moves objects to different locations in the heap. When the garbage collector moves an object the garbage collector also updates all handles that refer to the object with the object's new location.
Seeing as though I cannot interact with v8 in my uv worker function, do I need to be concerned about my data moving if I store a persistent handle at my class level and then pass a pointer to my data into my worker function? In other words, does the persistent handle guarantee that the pointer I get from
node::Buffer::Datawill remain valid?The memory that the buffer object points to won't move but the object itself can. Rule of thumb: don't interact with node or V8 when on a different thread. That means you shouldn't call e.g.
node::Buffer::Data()from the thread pool.Makes sense, so by that logic if I store a pointer to the data (i.e., as a
char *obtained fromnode::Buffer::Data()) in my class, it should be safe to consume that data in a worker thread as long as the Buffer itself is contained in aPersistenthandle (also as a class variable). Does that sound correct?Yes, 100% correct.
@bnoordhuis Awesome, thanks again!
I'm working on an asynchronous C++ addon that is going to be processing buffers piped in from a stream, and I'm wondering the best way to persist the buffer data from the main event-loop thread into my worker thread. I'm basing much of my design on the way the Node.js zlib module is structured in the sense that I'm exposing a process function of my class that looks something like:
My question is whether or not the
unsigned char *bufwill persist throughout the lifetime of my class, or as I suspect, I will need to create a local copy of the data. I'm wondering if there is a way to force v8 to persist the data until I release it, but I'm just getting into the deep-end (or maybe the shallow end...) of interacting with v8 and would appreciate any guidance on how stuff like this is typically accomplished.