Skip to content

Instantly share code, notes, and snippets.

@trevnorris
Created February 5, 2016 23:53
Show Gist options
  • Save trevnorris/a142a82bd75c686497c3 to your computer and use it in GitHub Desktop.
Save trevnorris/a142a82bd75c686497c3 to your computer and use it in GitHub Desktop.
Run a callback when an object is GC'd
#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)
'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