Created
February 5, 2016 23:53
-
-
Save trevnorris/a142a82bd75c686497c3 to your computer and use it in GitHub Desktop.
Run a callback when an object is GC'd
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <v8.h> | |
#include <node.h> | |
using namespace v8; | |
typedef void (*FreeCallback)(Local<Object> object, Local<Function> fn); | |
class CallbackStuff { | |
public: | |
static inline CallbackStuff* New(Isolate* isolate, | |
Local<Object> object, | |
Local<Function> fn, | |
FreeCallback callback); | |
inline Persistent<Object>* persistent(); | |
private: | |
static void WeakCallback(const WeakCallbackData<Object, CallbackStuff>&); | |
inline void WeakCallback(Isolate* isolate, Local<Object> object); | |
inline CallbackStuff(Isolate* isolate, | |
Local<Object> object, | |
Local<Function> fn, | |
FreeCallback callback); | |
~CallbackStuff(); | |
Persistent<Object> persistent_; | |
Persistent<Function> fn_; | |
FreeCallback const callback_; | |
}; | |
CallbackStuff* CallbackStuff::New(Isolate* isolate, | |
Local<Object> object, | |
Local<Function> fn, | |
FreeCallback callback) { | |
return new CallbackStuff(isolate, object, fn, callback); | |
} | |
Persistent<Object>* CallbackStuff::persistent() { | |
return &persistent_; | |
} | |
CallbackStuff::CallbackStuff(Isolate* isolate, | |
Local<Object> object, | |
Local<Function> fn, | |
FreeCallback callback) | |
: persistent_(isolate, object), | |
fn_(isolate, fn), | |
callback_(callback) { | |
persistent_.SetWeak(this, WeakCallback); | |
persistent_.MarkIndependent(); | |
} | |
CallbackStuff::~CallbackStuff() { | |
persistent_.Reset(); | |
fn_.Reset(); | |
} | |
void CallbackStuff::WeakCallback( | |
const WeakCallbackData<Object, CallbackStuff>& data) { | |
data.GetParameter()->WeakCallback(data.GetIsolate(), data.GetValue()); | |
} | |
void CallbackStuff::WeakCallback(Isolate* isolate, Local<Object> object) { | |
HandleScope scope(isolate); | |
callback_(object, Local<Function>::New(isolate, fn_)); | |
delete this; | |
} | |
// JS Export Functions | |
// This callback is called when the object is GC'd | |
void FreeObjectCallback(Local<Object> object, Local<Function> fn) { | |
Local<Value> val = object.As<Value>(); | |
fn->Call(Null(object->GetIsolate()), 1, &val); | |
} | |
void Run(const FunctionCallbackInfo<Value>& args) { | |
assert(args[0]->IsObject()); | |
assert(args[1]->IsFunction()); | |
CallbackStuff::New(args.GetIsolate(), | |
args[0].As<Object>(), | |
args[1].As<Function>(), | |
FreeObjectCallback); | |
} | |
void Init(Handle<Object> target) { | |
NODE_SET_METHOD(target, "run", Run); | |
} | |
NODE_MODULE(addon, Init) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
const run = require('./build/Release/addon').run; | |
const print = process._rawDebug; | |
var o; | |
run({ foo: 42 }, function(obj) { | |
o = obj; | |
print('hi all'); | |
}); | |
var arr = []; | |
for (var i = 0; i < 1e6; i++) { | |
arr.push({}); | |
} | |
setTimeout(function() { | |
print(o); | |
}, 100); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment