Instantly share code, notes, and snippets.

What would you like to do?
#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);
// 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[] =
// execute the callback
// dispose the callback object from the baton
// 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-> = 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]);
// 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
// nothing returned
return Undefined();
void init(Handle<Object> exports) {
// add the async function to the exports for this object
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() {
// 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" ]

This comment has been minimized.

Copy link

JoneXie1986 commented Oct 15, 2015



This comment has been minimized.

Copy link

paulhauner commented Apr 13, 2016

I couldn't get this to work though - could be my shabby C++ or maybe Node.js versioning.
I've got a version working with Node.js v4.4.2 running here:


This comment has been minimized.

Copy link

Globik commented Aug 7, 2016

@paulhauner and what is node.js 6? :) is working this asynch sample?


This comment has been minimized.

Copy link

ustulation commented Sep 15, 2017

@dmh2000 :
I wanted NodeJS to call C code which accepts a function pointer to give back the result asynchronously to the caller. I stumbled upon this and it's very helpful 👍 as I know almost nothing about NodeJS (javascript in general). I was expecting two have only 2 threads in total in my setup - a main thread which is the JS event loop and a background event loop which is in C.

C code:

void foo(char *param_0, int param_1, void *user_data, void(*output)(void * /*user_data*/, int /*some-result*/)) {
  // Post the 4 function parameters to C event loop running in a background thread.
  // When C finishes, it'll notify the outcome via given `output` function-ptr/callback in it's thread.
  // The call back should have the logic to post to JS main event loop thread and return.

So calling foo is non-blocking.

However it seems that i need to code a wrapper around foo (which equivalently would be delay() in your example) which will call foo giving it a callback written in C and block until result is obtained via passed callback. This wrapper (the equivalent of delay) will be called in a worker thread spawned by libuv according to your explanation. This means that each time NodeJS wants to call foo a new thread will be spawned by the libuv intermediary, thus could end up having potentially 100s or threads assuming rate of calling foo is higher than C processing the result and returning it via callback.

Is that true ? Is this a standard idiom or is there a way around it (to have just 2 or 3 threads like described) ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment