Skip to content

Instantly share code, notes, and snippets.

@johnhaley81
Created February 27, 2015 19:17
Show Gist options
  • Save johnhaley81/24686896ea2fed936ac3 to your computer and use it in GitHub Desktop.
Save johnhaley81/24686896ea2fed936ac3 to your computer and use it in GitHub Desktop.
`uv_async_init`
#ifndef PAYLOAD_WRAPPER_H
#define PAYLOAD_WRAPPER_H
#include <v8.h>
#include <node.h>
#include "nan.h"
using namespace v8;
using namespace node;
struct PayloadWrapper {
NanCallback* jsCallback;
uv_async_t handle;
};
#endif
// This is run in the main loop
NAN_METHOD(GitStatus::ForeachExt)
{
NanScope();
ForeachExtBaton* baton = new ForeachExtBaton;
baton->error_code = GIT_OK;
baton->error = NULL;
ForeachExt_globalPayload* globalPayload = new ForeachExt_globalPayload;
git_repository * from_repo;
from_repo = ObjectWrap::Unwrap<GitRepository>(args[0]->ToObject())->GetValue();
baton->repo = from_repo;
const git_status_options * from_opts;
from_opts = ObjectWrap::Unwrap<GitStatusOptions>(args[1]->ToObject())->GetValue();
baton->opts = from_opts;
baton->callback = ForeachExt_callback_cppCallback;
globalPayload->callback = new PayloadWrapper();
globalPayload->callback->jsCallback = new NanCallback(args[2].As<Function>());
uv_async_init(uv_default_loop(), &globalPayload->callback->handle, ForeachExt_callback_async);
baton->payload = globalPayload;
NanCallback *callback = new NanCallback(Local<Function>::Cast(args[4]));
ForeachExtWorker *worker = new ForeachExtWorker(baton, callback);
if (!args[0]->IsUndefined() && !args[0]->IsNull()) {
worker->SaveToPersistent("repo", args[0]->ToObject());
}
if (!args[1]->IsUndefined() && !args[1]->IsNull()) {
worker->SaveToPersistent("opts", args[1]->ToObject());
}
if (!args[3]->IsUndefined() && !args[3]->IsNull()) {
worker->SaveToPersistent("payload", args[3]->ToObject());
}
NanAsyncQueueWorker(worker);
NanReturnUndefined();
}
// This is run outside of the main loop
void GitStatus::ForeachExtWorker::Execute()
{
int result = git_status_foreach_ext(
baton->repo,baton->opts,baton->callback,baton->payload );
baton->error_code = result;
if (result != GIT_OK && giterr_last() != NULL) {
baton->error = git_error_dup(giterr_last());
}
}
// This is run in the main loop
void GitStatus::ForeachExtWorker::HandleOKCallback()
{
TryCatch try_catch;
if (baton->error_code == GIT_OK) {
Handle<v8::Value> result = NanUndefined();
Handle<v8::Value> argv[2] = {
NanNull(),
result
};
callback->Call(2, argv);
} else {
if (baton->error) {
Handle<v8::Value> argv[1] = {
NanError(baton->error->message)
};
callback->Call(1, argv);
if (baton->error->message)
free((void *)baton->error->message);
free((void *)baton->error);
} else {
callback->Call(0, NULL);
}
}
if (try_catch.HasCaught()) {
node::FatalException(try_catch);
}
delete (ForeachExt_globalPayload*)baton->payload;
delete baton;
}
// This is run outside of the main loop
int GitStatus::ForeachExt_callback_cppCallback (
const char * path, unsigned int status_flags, void * payload )
{
ForeachExt_CallbackBaton* baton = new ForeachExt_CallbackBaton();
baton->path = path;
baton->status_flags = status_flags;
baton->payload = payload;
baton->req = &((ForeachExt_globalPayload*)payload)->callback->handle;
baton->result = 0;
baton->req->data = baton;
baton->done = false;
uv_async_send(baton->req);
while(!baton->done) {
this_thread::sleep_for(chrono::milliseconds(1));
}
return baton->result;
}
// This is run in the main loop
void GitStatus::ForeachExt_callback_async(uv_async_t* req, int status)
{
NanScope();
ForeachExt_CallbackBaton* baton = static_cast<ForeachExt_CallbackBaton*>(req->data);
NanCallback* callback = ((ForeachExt_globalPayload*)baton->payload)->callback->jsCallback;
Local<Value> argv[3] = {
NanNew(baton->path),
NanNew(baton->status_flags),
NanUndefined()
};
TryCatch tryCatch;
Handle<v8::Value> result = callback->Call(3, argv);
if (result.IsEmpty() || result->IsNativeError()) {
baton->result = -1;
} else if (!result->IsNull() && !result->IsUndefined()) {
if (result->IsNumber()) {
baton->result = (int)result->ToNumber()->Value();
} else {
baton->result = 0;
}
} else {
baton->result = 0;
}
baton->done = true;
}
#ifndef GITSTATUS_H
#define GITSTATUS_H
// generated from class_header.h
#include <nan.h>
#include <string>
extern "C" {
#include <git2.h>
#include <git2/sys/diff.h>
}
#include "../include/repository.h"
#include "../include/status_options.h"
#include "payload_wrapper.h"
using namespace node;
using namespace v8;
class GitStatus : public ObjectWrap {
public:
static Persistent<Function> constructor_template;
static void InitializeComponent (Handle<v8::Object> target);
static void ForeachExt_callback_async(uv_async_t* req, int status);
struct ForeachExt_CallbackBaton {
const char * path;
unsigned int status_flags;
void * payload;
uv_async_t* req;
int result;
Persistent<Object> promise;
bool done;
};
private:
struct ForeachExtBaton {
int error_code;
const git_error* error;
git_repository * repo;
const git_status_options * opts;
git_status_cb callback;
void * payload;
};
class ForeachExtWorker : public NanAsyncWorker {
public:
ForeachExtWorker(
ForeachExtBaton *_baton,
NanCallback *callback
) : NanAsyncWorker(callback)
, baton(_baton) {};
~ForeachExtWorker() {};
void Execute();
void HandleOKCallback();
private:
ForeachExtBaton *baton;
};
static NAN_METHOD(ForeachExt);
struct ForeachExt_globalPayload {
PayloadWrapper * callback;
ForeachExt_globalPayload() {
callback = NULL;
}
~ForeachExt_globalPayload() {
if (callback != NULL) {
delete callback;
}
}
};
};
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment