-
-
Save Sequoia/6d1dafe56e3916559a66567360ceb498 to your computer and use it in GitHub Desktop.
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 <unistd.h> | |
#include <node.h> | |
#include <string.h> | |
#include <v8.h> | |
using namespace v8; | |
unsigned long long count = 0; | |
// native blocking/compute intensive function | |
void delay(int seconds) { | |
int i; | |
int j; | |
// a long computation | |
for(i=0;i<2000000;++i) { | |
for(j=0;j<400;++j) { | |
count = count * seconds; | |
} | |
} | |
/** | |
* or a blocking call | |
* sleep(seconds); | |
*/ | |
} | |
// the 'baton' is the carrier for data between functions | |
struct DelayBaton | |
{ | |
// required | |
uv_work_t request; // libuv | |
Persistent<Function> callback; // javascript callback | |
// optional : data goes here. | |
// data that doesn't go back to javascript can be any typedef | |
// data that goes back to javascript needs to be a supported type | |
int seconds; | |
char greeting[256]; | |
}; | |
// called by libuv worker in separate thread | |
static void DelayAsync(uv_work_t *req) | |
{ | |
DelayBaton *baton = static_cast<DelayBaton *>(req->data); | |
delay(baton->seconds); | |
} | |
// called by libuv in event loop when async function completes | |
static void DelayAsyncAfter(uv_work_t *req,int status) | |
{ | |
// get the reference to the baton from the request | |
DelayBaton *baton = static_cast<DelayBaton *>(req->data); | |
// set up return arguments | |
Handle<Value> argv[] = | |
{ | |
Handle<Value>(Int32::New(baton->seconds)), | |
Handle<Value>(String::New(baton->greeting)) | |
}; | |
// execute the callback | |
baton->callback->Call(Context::GetCurrent()->Global(),2,argv); | |
// dispose the callback object from the baton | |
baton->callback.Dispose(); | |
// delete the baton object | |
delete baton; | |
} | |
// javascript callable function | |
Handle<Value> Delay(const Arguments &args) | |
{ | |
// create 'baton' data carrier | |
DelayBaton *baton = new DelayBaton; | |
// get callback argument | |
Handle<Function> cb = Handle<Function>::Cast(args[2]); | |
// attach baton to uv work request | |
baton->request.data = baton; | |
// assign incoming arguments to baton | |
baton->seconds = args[0]->Int32Value(); | |
// point at the argument as a string, then copy it to the baton | |
v8::String::Utf8Value str(args[1]); | |
strncpy(baton->greeting,*str,sizeof(baton->greeting)); | |
// assign callback to baton | |
baton->callback = Persistent<Function>::New(cb); | |
// queue the async function to the event loop | |
// the uv default loop is the node.js event loop | |
uv_queue_work(uv_default_loop(),&baton->request,DelayAsync,DelayAsyncAfter); | |
// nothing returned | |
return Undefined(); | |
} | |
void init(Handle<Object> exports) { | |
// add the async function to the exports for this object | |
exports->Set( | |
String::NewSymbol("delay"), // javascript function name | |
FunctionTemplate::New(Delay)->GetFunction() // attach 'Delay' function to javascript name | |
); | |
} | |
NODE_MODULE(delay, init) | |
/** | |
* server.js | |
var addon = require('./build/Release/delay'); | |
var i = 0; | |
setInterval(function() { | |
console.log(i++); | |
},500); | |
// test the delay function | |
addon.delay(3,'hello world',function(a,b) { | |
console.log('delay : ' + a + ',' + b); | |
}); | |
*/ | |
/** | |
* binding.gyp | |
{ | |
"targets": [ | |
{ | |
"target_name": "delay", | |
"sources": [ "delay.cpp" ] | |
} | |
] | |
} | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment