My assumption is that my test app terminates before the GC has a chance to 
run.
To test this:

   - I run node with the --expose-gc option
   - I call global.gc() at the end of my test app

In this case, the destructor of my ObjectWrap is indeed called.

*So it seams the GC doesn't simply "collect everything" when the app 
terminates.*
*Why is that?*

It sounds like a pretty bad things to do: some behaviors might expect the 
destructor to be called in order to close a socket, etc...

On Friday, November 17, 2017 at 10:27:22 AM UTC+1, Jean-Marc Le Roux wrote:
>
> Thanks for the great help!
> I think it makes a lot of sense now.
>
> So I've extended ObjectWrap like so:
>
> class BSONObject : public node::ObjectWrap
>> {
>> private:
>>     bson_t* _bson;
>> public:
>>     BSONObject(bson_t* bson, Local<ObjectTemplate> tpl) :
>>         _bson(bson)
>>     {
>>         Local<Object> obj = tpl->NewInstance();
>>         initialize(v8::Isolate::GetCurrent(), obj, bson);
>>         Wrap(obj);
>>     }
>
>  
>
>  ~BSONObject()
>>     {
>>         std::cout << "~BSONObject()" << std::endl;
>>         bson_destroy(_bson);
>>     }
>
>  
>
>     static
>>     Local<ObjectTemplate>
>>     create_template(Isolate* isolate, const bson_t* document)
>>     {
>>         Local<ObjectTemplate> tpl = ObjectTemplate::New(isolate);
>>         tpl->SetInternalFieldCount(1); 
>
>
> And the "insert" function that I expose in JS and that instanciates the 
> BSONObject is written like this:
>
> void
>> insert(const FunctionCallbackInfo<Value>& args)
>> {
>>     Isolate* isolate = args.GetIsolate();
>>     
>>     db->insert(
>>         json_stringify(isolate, args[0]),
>>         [&args, isolate](const bson_t* document)
>>         {
>>             if (!args[1]->IsUndefined())
>>             {
>>                 Local<Function> callback = Local<Function>::Cast(args[1]);
>>                 Local<Object> obj = Object::New(isolate);
>>                 *Local<Value> argv[] = { (new 
>> BSONObject(bson_copy(document)))->handle(isolate) };*
>>                 callback->Call(isolate->GetCurrentContext()->Global(), 1, 
>> argv);
>>             }
>>         }
>>     );
>> }
>
>
> It runs fine.
> But the destructor is never called (I never see "~BSONObject()" on stdout).
>
> Did I miss something?
>
> Thanks !
>
> 2017-11-16 22:01 GMT+01:00 J Decker <d3c...@gmail.com>:
>
>> You don't manage the instance, the v8 engine does.  When it's no longer 
>> referenced in the engine, it's garbage collected which triggers the 
>> callback set when the perisstent object is made weak.
>>
>> You don't need to keep it anywhere, the object returned into the engine 
>> has Internal Fields ( SetInternalFieldCount(1) ) which is used to point to 
>> your native class instance.   So when the callback is called, it knows what 
>> to call to destruct it.
>>
>> You have to 'keep it' in the javascript scrpit if you want to keep it, 
>> it's not 'kept' in the native code...
>>
>>
>> --- This is some code I've done that uses setweak directly; but it's 
>> fairly scattered....
>>
>> https://github.com/d3x0r/sack.vfs/blob/master/src/jsonParse.cc#L18
>>
>> You can create an instance of your wrapped object with
>>
>> Local<Function> cons = Local<Function>::New( isolate, constructor );
>>     cons->NewInstance( isolate->GetCurrentContext(), argc, argv      
>> ).ToLocalChecked() ;
>>
>> Hmm that's not the best example source... 
>>
>> https://github.com/d3x0r/sack.vfs/blob/master/src/vfs_module.cc#L407
>>
>> This creates a buffer, and makes it weak... 
>> https://github.com/d3x0r/sack.vfs/blob/master/src/vfs_module.cc#L438
>>
>> Local<Object> arrayBuffer = ArrayBuffer::New( isolate, buf, len );
>> PARRAY_BUFFER_HOLDER holder = GetHolder();
>> holder->o.Reset( isolate, arrayBuffer );
>> holder->o.SetWeak<ARRAY_BUFFER_HOLDER>( holder, releaseBuffer, 
>> WeakCallbackType::kParameter );
>> holder->buffer = buf;
>>
>> PARRAY_BUFFER_HOLDER is just a type that holds the thing to be free (or 
>> object containing things to be released), and the persistent reference that 
>> has been made weak...
>>
>> struct arrayBufferHolder {
>> void *buffer;
>> Persistent<Object> o;
>> };
>>
>>
>>
>> On Thu, Nov 16, 2017 at 9:56 AM, Jean-Marc Le Roux <
>> jeanmarc.ler...@aerys.in> wrote:
>>
>>> Node offers a C++ Clss extention ObjectWrap 
>>>
>>>
>>> Thanks !
>>> It is related to node. Yet I'm not sure how I'm supposed to use 
>>> ObjectWrap.
>>>
>>> I understand I have to create my own class that extends ObjectWrap and 
>>> implement a proper destructor.
>>> Then I'll instanciate that class to wrap my Local<Object>. But how do I 
>>> manage such instance?
>>> If I don't keep it somewhere, it will be destructed.
>>> If I keep it around, then I'm keeping references to potentially 
>>> deallocated memory.
>>>
>>> It feels like I end up with the same problem...
>>>
>>> 2017-11-16 18:36 GMT+01:00 J Decker <d3c...@gmail.com>:
>>>
>>>>
>>>>
>>>> On Thu, Nov 16, 2017 at 1:24 AM, Jean-Marc Le Roux <
>>>> jeanmarc.ler...@aerys.in> wrote:
>>>>
>>>>> I assume you're storing references to the objects as Persistent?
>>>>>
>>>>>
>>>>> Nope. You've got the whole code up there.
>>>>> So if I understand correctly:
>>>>>
>>>>>    - the objects I need to keep track of the lifecycle should be made 
>>>>>    Persistent ;
>>>>>    - all the other values can be set as Local ;
>>>>>    - I should set the weak callback using MakeWeak ;
>>>>>    - callback will be called when such object is GCed and I can free 
>>>>>    my C/C++ memory then.
>>>>>
>>>>> Is that correct ?
>>>>>
>>>>
>>>> Yes.  I sthis perhaps related to Node?
>>>> Node offers a C++ Clss extention ObjectWrap 
>>>>
>>>> https://nodejs.org/api/addons.html#addons_wrapping_c_objects
>>>> https://github.com/nodejs/node/blob/master/src/node_object_wrap.h 
>>>>
>>>> which simplifies that whole process... when the object is GC'd the 
>>>> class destructor will get called so you can release values there.
>>>>
>>>>  
>>>>
>>>>>
>>>>> 2017-11-15 19:50 GMT+01:00 J Decker <d3c...@gmail.com>:
>>>>>
>>>>>> I assume you're storing references to the objects as Persistent?  All 
>>>>>> you need to do then is call SetWeak() 
>>>>>> https://v8docs.nodesource.com/node-0.10/d2/d78/classv8_1_1_persistent.html
>>>>>> void MakeWeak (void *parameters, WeakReferenceCallback callback)
>>>>>>
>>>>>> the callback is called when the object is GC'd.
>>>>>>
>>>>>>
>>>>>> On Wed, Nov 15, 2017 at 8:37 AM, Jean-Marc Le Roux <
>>>>>> jeanmarc.ler...@aerys.in> wrote:
>>>>>>
>>>>>>> So I've found a solution to make things lazy: I set an accessor 
>>>>>>> instead of decoding/setting the actual value.
>>>>>>>
>>>>>>> void
>>>>>>> getter(Local<Name> property, const PropertyCallbackInfo<Value>& info)
>>>>>>> {
>>>>>>>     Isolate* isolate = info.GetIsolate();
>>>>>>>
>>>>>>>       const bson_t* document = reinterpret_cast<bson_t*>(
>>>>>>>         info.This()
>>>>>>>             ->Get(String::NewFromUtf8(isolate, 
>>>>>>> "__bson_document_ptr"))
>>>>>>>             ->ToInt32()->Value()
>>>>>>>     );
>>>>>>>
>>>>>>>     char key[255];
>>>>>>>     property->ToString(isolate)->WriteUtf8(key, 255);
>>>>>>>
>>>>>>>     bson_iter_t iter;
>>>>>>>     bson_iter_init(&iter, document);
>>>>>>>     // FIXME: index the property so we don't have to find it
>>>>>>>     bson_iter_find(&iter, key);
>>>>>>>
>>>>>>>     // FIXME: replace the accessor with the deserialized value
>>>>>>>
>>>>>>>     info.GetReturnValue().Set(iterator_to_value(isolate, &iter));
>>>>>>> }
>>>>>>>
>>>>>>> Local<Value>
>>>>>>> fill_object(Isolate* isolate, Local<Object>& obj, const bson_t* 
>>>>>>> document)
>>>>>>> {
>>>>>>>     obj->Set(
>>>>>>>         String::NewFromUtf8(isolate, "__bson_document_ptr"),
>>>>>>>         Int32::New(isolate, reinterpret_cast<intptr_t>(document))
>>>>>>>     );
>>>>>>>
>>>>>>>     bson_iter_t iter;
>>>>>>>     if (bson_iter_init(&iter, document))
>>>>>>>     {
>>>>>>>         while (bson_iter_next(&iter))
>>>>>>>         {
>>>>>>>             const char* key = bson_iter_key(&iter);
>>>>>>>
>>>>>>>                         if (!obj->Has(String::NewFromUtf8(isolate, 
>>>>>>> key))) 
>>>>>>>             {
>>>>>>>                 obj->SetAccessor(
>>>>>>>                     isolate->GetCurrentContext(),
>>>>>>>                     String::NewFromUtf8(isolate, key),
>>>>>>>                     &getter
>>>>>>>                 );
>>>>>>>             }
>>>>>>>                 }
>>>>>>>     }
>>>>>>> }
>>>>>>>
>>>>>>> The secret sauce is to :
>>>>>>>
>>>>>>>    - keep the original data (the bson_t) allocated
>>>>>>>    - store the corresponding pointer in a v8::Object
>>>>>>>
>>>>>>> But now I have a memory leak because those pointers will never be 
>>>>>>> freed.
>>>>>>> How can I know when the Object will be disposed by the GC?
>>>>>>>
>>>>>>> Thanks,
>>>>>>>
>>>>>>> -- 
>>>>>>> -- 
>>>>>>> v8-users mailing list
>>>>>>> v8-users@googlegroups.com
>>>>>>> http://groups.google.com/group/v8-users
>>>>>>> --- 
>>>>>>> You received this message because you are subscribed to the Google 
>>>>>>> Groups "v8-users" group.
>>>>>>> To unsubscribe from this group and stop receiving emails from it, 
>>>>>>> send an email to v8-users+unsubscr...@googlegroups.com.
>>>>>>> For more options, visit https://groups.google.com/d/optout.
>>>>>>>
>>>>>>
>>>>>> -- 
>>>>>> -- 
>>>>>> v8-users mailing list
>>>>>> v8-users@googlegroups.com
>>>>>> http://groups.google.com/group/v8-users
>>>>>> --- 
>>>>>> You received this message because you are subscribed to a topic in 
>>>>>> the Google Groups "v8-users" group.
>>>>>> To unsubscribe from this topic, visit 
>>>>>> https://groups.google.com/d/topic/v8-users/aVeevQcHJ2c/unsubscribe.
>>>>>> To unsubscribe from this group and all its topics, send an email to 
>>>>>> v8-users+unsubscr...@googlegroups.com.
>>>>>> For more options, visit https://groups.google.com/d/optout.
>>>>>>
>>>>>
>>>>>
>>>>>
>>>>> -- 
>>>>> *Jean-Marc Le Roux*
>>>>>
>>>>>
>>>>> Founder and CEO of Aerys (http://aerys.in)
>>>>>
>>>>> Blog: http://blogs.aerys.in/jeanmarc-leroux
>>>>> Cell: (+33)6 20 56 45 78
>>>>> Phone: (+33)9 72 40 17 58
>>>>>
>>>>> -- 
>>>>> -- 
>>>>> v8-users mailing list
>>>>> v8-users@googlegroups.com
>>>>> http://groups.google.com/group/v8-users
>>>>> --- 
>>>>> You received this message because you are subscribed to the Google 
>>>>> Groups "v8-users" group.
>>>>> To unsubscribe from this group and stop receiving emails from it, send 
>>>>> an email to v8-users+unsubscr...@googlegroups.com.
>>>>> For more options, visit https://groups.google.com/d/optout.
>>>>>
>>>>
>>>> -- 
>>>> -- 
>>>> v8-users mailing list
>>>> v8-users@googlegroups.com
>>>> http://groups.google.com/group/v8-users
>>>> --- 
>>>> You received this message because you are subscribed to a topic in the 
>>>> Google Groups "v8-users" group.
>>>> To unsubscribe from this topic, visit 
>>>> https://groups.google.com/d/topic/v8-users/aVeevQcHJ2c/unsubscribe.
>>>> To unsubscribe from this group and all its topics, send an email to 
>>>> v8-users+unsubscr...@googlegroups.com.
>>>> For more options, visit https://groups.google.com/d/optout.
>>>>
>>>
>>>
>>>
>>> -- 
>>> *Jean-Marc Le Roux*
>>>
>>>
>>> Founder and CEO of Aerys (http://aerys.in)
>>>
>>> Blog: http://blogs.aerys.in/jeanmarc-leroux
>>> Cell: (+33)6 20 56 45 78
>>> Phone: (+33)9 72 40 17 58
>>>
>>> -- 
>>> -- 
>>> v8-users mailing list
>>> v8-users@googlegroups.com
>>> http://groups.google.com/group/v8-users
>>> --- 
>>> You received this message because you are subscribed to the Google 
>>> Groups "v8-users" group.
>>> To unsubscribe from this group and stop receiving emails from it, send 
>>> an email to v8-users+unsubscr...@googlegroups.com.
>>> For more options, visit https://groups.google.com/d/optout.
>>>
>>
>> -- 
>> -- 
>> v8-users mailing list
>> v8-users@googlegroups.com
>> http://groups.google.com/group/v8-users
>> --- 
>> You received this message because you are subscribed to a topic in the 
>> Google Groups "v8-users" group.
>> To unsubscribe from this topic, visit 
>> https://groups.google.com/d/topic/v8-users/aVeevQcHJ2c/unsubscribe.
>> To unsubscribe from this group and all its topics, send an email to 
>> v8-users+unsubscr...@googlegroups.com.
>> For more options, visit https://groups.google.com/d/optout.
>>
>
>
>
> -- 
> *Jean-Marc Le Roux*
>
>
> Founder and CEO of Aerys (http://aerys.in)
>
> Blog: http://blogs.aerys.in/jeanmarc-leroux
> Cell: (+33)6 20 56 45 78
> Phone: (+33)9 72 40 17 58
>

-- 
-- 
v8-users mailing list
v8-users@googlegroups.com
http://groups.google.com/group/v8-users
--- 
You received this message because you are subscribed to the Google Groups 
"v8-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to v8-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to