Created
June 19, 2012 20:03
-
-
Save jedp/2956223 to your computer and use it in GitHub Desktop.
libuv simple async
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 <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