How do you free a wrapped C++ object when associated Javascript object is garbage collected in V8?

后端 未结 3 2020
攒了一身酷
攒了一身酷 2021-01-31 04:05

V8\'s documentation explains how to create a Javascript object that wraps a C++ object. The Javascript object holds on to a pointer to a C++ object instance. My question is, let

相关标签:
3条回答
  • 2021-01-31 04:59

    The trick is to create a Persistent handle (second bullet point from the linked-to API reference: "Persistent handles are not held on a stack and are deleted only when you specifically remove them. ... Use a persistent handle when you need to keep a reference to an object for more than one function call, or when handle lifetimes do not correspond to C++ scopes."), and call MakeWeak() on it, passing a callback function that will do the necessary cleanup ("A persistent handle can be made weak, using Persistent::MakeWeak, to trigger a callback from the garbage collector when the only references to an object are from weak persistent handles." -- that is, when all "regular" handles have gone out of scope and when the garbage collector is about to delete the object).

    The Persistent::MakeWeak method signature is:

    void MakeWeak(void* parameters, WeakReferenceCallback callback);
    

    Where WeakReferenceCallback is defined as a pointer-to-function taking two parameters:

    typedef void (*WeakReferenceCallback)(Persistent<Object> object,
                                          void* parameter);
    

    These are found in the v8.h header file distributed with V8 as the public API.

    You would want the function you pass to MakeWeak to clean up the Persistent<Object> object parameter that will get passed to it when it's called as a callback. The void* parameter parameter can be ignored (or the void* parameter can point to a C++ structure that holds the objects that need cleaning up):

    void CleanupV8Point(Persistent<Object> object, void*)
    {
        // do whatever cleanup on object that you're looking for
        object.destroyCppObjects();
    }
    
    Parameter<ObjectTemplate> my_obj(ObjectTemplate::New());
    
    // when the Javascript part of my_obj is about to be collected
    // we'll have V8 call CleanupV8Point(my_obj)
    my_obj.MakeWeak(NULL, &CleanupV8Point);
    
    0 讨论(0)
  • 2021-01-31 05:04

    Do all your work in some closed scope (of object or function). Then you can safely remove the C++ object when you went out of scope. GC doesn't check pointers for existence of pointed objects.

    0 讨论(0)
  • 2021-01-31 05:06

    In general, if a garbage-collected language can hold references to resources outside of the language engine (files, sockets, or in your case C++ objects), you should provide a 'close' method to release that resource ASAP, no point waiting until the GC thinks it's worthwhile to destroy your object.

    it gets worse if your C++ object is memory-hungry and the garbage-collected object is just a reference: you might allocate thousands of objects, and the GC only sees a few KB's of tiny objects, not enough to trigger collection; while the C++ side is struggling with tens of megabytes of stale objects.

    0 讨论(0)
提交回复
热议问题