public
Last active

A C header file to make your node bindings backwards and forwards compatible that use eio_custom()

  • Download Gist
README.md
Markdown

node_async_shim.h

Use this header file to conditionally invoke eio_custom() or uv_queue_work(), depending on the node version that the module is being compiled for.

See the usage.cc file for a partial example.

Comments, forks, and improvements are welcome!

node_async_shim.h
C++
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
/**
* eio_custom() vs. uv_queue_work() file.
* Original gist: https://gist.github.com/1368935
*
* Copyright (c) 2011-2012, Nathan Rajlich <nathan@tootallnate.net>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
 
#include <node.h>
#include <node_version.h>
 
/* Node Thread Pool version compat */
#if NODE_VERSION_AT_LEAST(0, 5, 6)
#define BEGIN_ASYNC(_data, async, after) \
uv_work_t *_req = new uv_work_t; \
_req->data = _data; \
uv_queue_work(uv_default_loop(), _req, async, after);
typedef void async_rtn;
#define RETURN_ASYNC
#define RETURN_ASYNC_AFTER delete req;
#else
#define BEGIN_ASYNC(data, async, after) \
ev_ref(EV_DEFAULT_UC); \
eio_custom(async, EIO_PRI_DEFAULT, after, data);
typedef int async_rtn;
typedef eio_req uv_work_t;
#define RETURN_ASYNC return 0;
#define RETURN_ASYNC_AFTER \
ev_unref(EV_DEFAULT_UC); \
RETURN_ASYNC;
#endif
usage.cc
C++
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
/**
* The "Thread Pool" function
*/
async_rtn doing_work (uv_work_t *req) {
my_struct *m = (my_struct *)req->data;
/* Something computationally expensive here */
r->rtn = 1 + 1;
RETURN_ASYNC
}
 
/**
* The "After" function
*/
async_rtn after_doing_work (uv_work_t *req) {
HandleScope scope;
 
my_struct *m = (my_struct *)req->data;
 
Handle<Value> argv[1];
argv[0] = Integer::New(r->rtn);
 
TryCatch try_catch;
m->callback->Call(Context::GetCurrent()->Global(), 1, argv);
if (try_catch.HasCaught())
FatalException(try_catch);
 
// cleanup
m->callback.Dispose();
delete m;
 
RETURN_ASYNC_AFTER
}
 
/**
* The JS Entry Point
*/
Handle<Value> start_doing_work (const Arguments& args) {
HandleScope scope;
 
my_struct *m = new my_struct;
m->callback = Persistent<Function>::New(Local<Function>::Cast(args[0]));
 
/* Start the async function on the thread pool */
BEGIN_ASYNC(m, doing_work, after_doing_work);
 
return Undefined();
}

Regardles to your defines, RETURN_ASYNC_AFTER and RETURN_ASYNC should be used without semicolon?)

@Sannis Ya you're right. It hasn't caused any compiler error for me though. I've updated the gist, thanks :)

Thanks, it will be more conform with node.h macroses.

This looks broken - you mention r->rtn - what is r?

Heyo Nate, I'm seeing maybe a missing header?

error: no matching function for call to 'uv_queue_work'
BEGIN_ASYNC(pm, asyncWriteTask, afterWriteTask);

checking recent v0.10.0 docs to see if uv_queue_work moved

oh, this may help

/Users/messel/.node-gyp/0.10.0/deps/uv/include/uv.h:1397:15: note: candidate function not viable: no known conversion from
      'async_rtn (uv_work_t *)' to 'uv_after_work_cb' (aka 'void (*)(uv_work_t *, int)') for 4th argument
UV_EXTERN int uv_queue_work(uv_loop_t* loop, uv_work_t* req,

looks like I need to convert the callback to
void (*)(uv_work_t *, int)

got it, just need to cast it.

#include 
#include 

/* Node Thread Pool version compat */
#if NODE_VERSION_AT_LEAST(0, 5, 6)
  #define BEGIN_ASYNC(_data, async, after) \
    uv_work_t *_req = new uv_work_t; \
    _req->data = _data; \
    uv_queue_work(uv_default_loop(), _req, async, (uv_after_work_cb)after);
  typedef void async_rtn;
  #define RETURN_ASYNC
  #define RETURN_ASYNC_AFTER delete req;
#else
  #define BEGIN_ASYNC(data, async, after) \
    ev_ref(EV_DEFAULT_UC); \
    eio_custom(async, EIO_PRI_DEFAULT, after, data);
  typedef int async_rtn;
  typedef eio_req uv_work_t;
  #define RETURN_ASYNC return 0;
  #define RETURN_ASYNC_AFTER \
    ev_unref(EV_DEFAULT_UC); \
    RETURN_ASYNC;
#endif

This does not work for 0.10.24 right? I tried it and it seemed to work, but then it said it could not find symbol module.

It seems a call to NODE_MODULE() is required now. Do you guys have any insights into this? If not, then I'd go and try to get it to work with https://github.com/rvagg/nan.

Thanks in advance for any pointers.

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.