Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to have a background thread call back to JS multiple times? #438

Closed
twoi opened this issue Jan 29, 2019 · 12 comments
Closed

How to have a background thread call back to JS multiple times? #438

twoi opened this issue Jan 29, 2019 · 12 comments

Comments

@twoi
Copy link

twoi commented Jan 29, 2019

TL;DR How can a long-running thread call a JS function repeatedly, i.e. without the use of AsyncWorker?

AsyncWorker seems to be for one long-running task that calls back to JS land only once, once finished.

In my scenario, a background thread is repeatedly calling back to JS land, something like relaying events that occur in native land to a JS callback. In the past (node.js 0.8), I did this with libuv's uv_async_send(), but I need to upgrade, and since uv and v8 have changed so much I thought I'd migrate straight over to node-addon-api, as it seems to have everything I need.

However I cannot seem to find out how to pull this off with AsyncContext and CallbackScope, which are made for cases like this, if I parse the docs correctly. However, all examples in the documentation and the tests in https://github.com/nodejs/node-addon-api/blob/master/test/ for both classes are (ironically?) working synchronously, and my attempts to migrate their callbacks over to run on a different thread have failed so far.

A nudge in the right direction on how to change either test/asyncworker.cc, test/callbackscope.cc or https://github.com/nodejs/node-addon-api/blob/master/doc/async_context.md#example to work asynchronously would be awesome. If I do get it to work in a reasonable amount of time, I promise I'll add a test and/or an example to node-addon-api.

(In order to be run on the JS thread, I'd expect I'd have to provide something like a function pointer, but I can't find anything to that effect in AsyncContext, CallbackScope, or Function::MakeCallback)

@twoi
Copy link
Author

twoi commented Jan 29, 2019

N.B. There is an example that seems to be doing something like I want to do, in plain N-API at https://github.com/nodejs/node-addon-examples/blob/master/async_work_thread_safe_function/node-api/

It is using *_threadsafe_function for that, which is nowhere to be found in the node-addon-api sources, so I guess I have to go N-API for this? (But then, what would AsyncContext and CallbackScope be good for?)

@twoi
Copy link
Author

twoi commented Jan 29, 2019

So the *_threadsafe_function isn't even part of the N-API included in the latest node-addon-api, which would mean I have to ditch node-addon-api and do everything with lower level N-API?

@romandev
Copy link
Contributor

@twoi, I think this issue is duplicated with #312

So the *_threadsafe_function isn't even part of the N-API included in the latest node-addon-api, which would mean I have to ditch node-addon-api and do everything with lower level N-API?

Yes, for now.

@DaAitch
Copy link
Contributor

DaAitch commented Jan 29, 2019

To your question @twoi thanks for asking.
Short version is (I hope this is still valid):

  • AsyncWorker uses nodejs computation threads, good for async short running tasks like algorithms to not block main loop, don't do long running tasks with it, like IO or sleeping/waiting, etc., you only have a few threads (fixed size pool)
  • tsfn is for making threadsafe calls into node, so you can use whatever thread impl you want

@twoi
Copy link
Author

twoi commented Jan 29, 2019

Thanks @romandev @DaAitch

But how can AsyncContext and CallbackScope be used asynchronously?

@twoi
Copy link
Author

twoi commented Feb 14, 2019

In the meantime, I've switched to the lower-level N-API to get the job done. It would still be great to be able to do this in node-addon-api, though. I find N-API not as easy to use as node-addon-api.

@gabrielschulhof
Copy link
Contributor

@twoi node-addon-api and N-API can be used together. While we don't yet have a node-addon-api wrapper around napi_threadsafe_function you can use the rest of node-addon-api together with napi_*_threadsafe_function(). You can use things like info.Env() from Napi::CallbackInfo info to obtain the napi_env you need, because a Napi::Env is automatically cast to a napi_env when you pass it into a N-API.

@gabrielschulhof
Copy link
Contributor

TBH I'm starting to think we should expose NAPI_THROW_IF_FAILED and NAPI_THROW_IF_FAILED_VOID because they're super-useful for mixing node-addon-api and N-API.

@legendecas
Copy link
Member

TBH I'm starting to think we should expose NAPI_THROW_IF_FAILED and NAPI_THROW_IF_FAILED_VOID because they're super-useful for mixing node-addon-api and N-API.

Is there any discussion on this idea? :P having these two in future n-api would be very helpful.

@mhdawson
Copy link
Member

mhdawson commented Mar 4, 2019

TBH I'm starting to think we should expose NAPI_THROW_IF_FAILED and NAPI_THROW_IF_FAILED_VOID because they're super-useful for mixing node-addon-api and N-API.

@legendecas just landed as: #448

@mhdawson
Copy link
Member

mhdawson commented Mar 4, 2019

@legendecas any remaining questions that need to be addressed in this issue. If not can you close it?

@twoi
Copy link
Author

twoi commented Mar 4, 2019

Let me close this. My question has been answered as "currently not possible with (pure) node-addon-api
"

@twoi twoi closed this as completed Mar 4, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants