Skip to content

Instantly share code, notes, and snippets.

@jedp
Created June 19, 2012 20:03
Show Gist options
  • Save jedp/2956223 to your computer and use it in GitHub Desktop.
Save jedp/2956223 to your computer and use it in GitHub Desktop.
libuv simple async
#include <v8.h>
#include <v8-profiler.h>
#include <node.h>
#include <uv.h>
#include <sys/time.h>
#include <iostream>
using namespace node;
using namespace v8;
using namespace std;
struct Baton {
uv_work_t request;
long start_ms;
int32_t snapshot;
Persistent<Function> callback;
int error_code;
std::string error_message;
// custom data
long result;
};
void AsyncSnapshotWork(uv_work_t* request) {
struct timeval end_time;
// blocking function - should not use any V8 code or even variable reads
// nb no handlescope here
Baton* baton = static_cast<Baton*>(request->data);
// do work in threadpool here
// set baton->error_code and error_message on failures
// convert values to C++ types and store them in the baton
gettimeofday(&end_time, NULL);
baton->result = ((end_time.tv_sec*1000) + (end_time.tv_usec/1000.0)) - baton->start_ms;
}
void AsyncSnapshotAfter(uv_work_t* request) {
HandleScope scope;
Baton* baton = static_cast<Baton*>(request->data);
if (baton->error_code) {
Local<Value> err = Exception::Error(String::New(
baton->error_message.c_str()));
Local<Value> argv[] = { err };
TryCatch try_catch;
baton->callback->Call(Context::GetCurrent()->Global(), 1, argv);
if (try_catch.HasCaught()) {
// throw an uncaughtException at the top of the loop
node::FatalException(try_catch);
}
} else {
const unsigned argc = 2;
Local<Value> argv[argc] = {
Local<Value>::New(Null()),
Local<Value>::New(Integer::New(baton->result))
};
TryCatch try_catch;
baton->callback->Call(Context::GetCurrent()->Global(), argc, argv);
if (try_catch.HasCaught()) {
node::FatalException(try_catch);
}
}
// because the callback is Permanent, we just delete it manually
baton->callback.Dispose();
delete baton;
}
static Handle<Value> AsyncSnapshot (const Arguments& args)
{
HandleScope scope;
struct timeval start_time;
const HeapSnapshot *hsn;
gettimeofday(&start_time, NULL);
if (!args[0]->IsFunction()) {
return ThrowException(Exception::TypeError(
String::New("Missing required callback function")));
}
Local<Function> callback = Local<Function>::Cast(args[0]);
Baton *baton = new Baton();
baton->start_ms = ((start_time.tv_sec*1000) + (start_time.tv_usec/1000.0));
hsn = HeapProfiler::TakeSnapshot(String::New("snapshot"));
baton->request.data = baton;
baton->callback = Persistent<Function>::New(callback);
baton->snapshot = hsn->GetNodesCount();
uv_queue_work(uv_default_loop(), &baton->request,
AsyncSnapshotWork, AsyncSnapshotAfter);
return Undefined();
}
extern "C"
{
static void init(Handle<Object> target)
{
NODE_SET_METHOD(target, "snapshot", AsyncSnapshot);
}
NODE_MODULE(heapstats, init);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment