-
Notifications
You must be signed in to change notification settings - Fork 464
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
Issues with the new ThreadSafeFunction api #524
Comments
@extmchristensen, @gabrielschulhof who it probably the best person to comment is away for another week so it might be after that when we engage in a discussion on this. |
Any news on when the copy constructor will be implemented? |
Having the same issue as 1), I tried to convert the lambda callback to a functor that was going to hold the ThreadSafeFunction, but for some reason I didn't manage to get it to compile. |
|
@mhdawson / @gabrielschulhof , I was thinking about what we said regarding these points:
I don't feel like it is necessary to tie acquire & release to copy + destruction... What was the reasoning behind this? I think it had something to do with race conditions? Would these race conditions still exist if we were using a normal napi Likewise, with the concern of overwriting a ThreadSafeFunction tsfn;
tsfn = ThreadSafeFunction::New(...);
tsfn = ThreadSafeFunction::New(...); ... would end up leaking the first TSFN... I feel like we should not need to specifically handle this case... eg, what would happen in the regular napi case? napi_threadsafe_function tsfn;
napi_create_threadsafe_function(..., &tsfn);
napi_create_threadsafe_function(..., &tsfn); .. the first TSFN reference is lost, no? Going back to @gabrielschulhof 's overall mantra of "the TSFN wrapper shouldn't have too much logic" ... using the ThreadSafeFunction correctly (eg don't try to copy it into another thread when the tsfn is no longer available) would be up to the developer, which in a lot of instances it already is anyway (eg. if you get a One thing I see (which I think we brought up) is that the copied |
@KevinEady I understand your point, but @extmchristensen 1. point is real, since I am using ThreadSafeFunction together with a Promise, if I chain two calls in the JS that will use the same The main problem is my code calls Promise.Resolve() before So the example doesn't really work in real life code, unless I am missing something. |
@marco-ms Sorry, I'm just trying to understand your use-case... Why are you re-assigning tsfn? |
What I have been doing is exposing two functions:
It'll crash since b calls blocking until JavaScript code is done, a's kicks in and will redefine tfsn and will crash with the error mentioned above.
This way each time I call a method it'll have its own tsfn instance and will be released during dtor, however for some reason Electron is now crashing randomly with:
And I haven't figured out why. |
Hi @gabrielschulhof , I'm working on the copy constructor, and I'm thinking back to something you said regarding the underlying I'm concerned that if we're using pointers, we'll need to take special care of the memory, as |
Removes the `unique_ptr` from `ThreadSafeFunction`, thereby allowing copies. Ref: nodejs#524
Is this issue still relevant? cc @mhdawson |
Part 3 & 4 is still relevant - part1+2 solved |
Take a look at this post. In all actuality, the thread count is just that: a counter. Even if you set it to In the specific example, it is set to
I feel like this can be solved programmatically by the developer...? If the last item you add to the queue performs some callback, you can perform some logic there. The underlying N-API does not have any functionality for this, so I don't think node-addon-api can provide this. |
This issue is stale because it has been open many days with no activity. It will be closed soon unless the stale label is removed or a comment is made. |
I'm going to close this since its been a long time since the last response. Please let us know if you think that was not the right thing to do. |
* tsfn: Implement copy constructor Refs: nodejs/node-addon-api#524 PR-URL: nodejs/node-addon-api#546 Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com> Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
* tsfn: Implement copy constructor Refs: nodejs/node-addon-api#524 PR-URL: nodejs/node-addon-api#546 Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com> Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
* tsfn: Implement copy constructor Refs: nodejs/node-addon-api#524 PR-URL: nodejs/node-addon-api#546 Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com> Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
* tsfn: Implement copy constructor Refs: nodejs/node-addon-api#524 PR-URL: nodejs/node-addon-api#546 Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com> Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
@romandev I am enthusiastically trying to use the new ThreadSafeFunction Api as a replacement for the non-standard napi-thread-safe-callback which I was using previously. I have a few problems though in my (typical?) use case where I have async native C++ functions that return quickly to JS but continue to do the actual work in an async C++ worker or thread, calling back into JS with progress information and/or result(s) using ThreadSafeFunction.
NB: Updated to show that issue 1 & 2 is now solved
1) SOLVED: Most importantly, the ThreadSafeCallback class is lacking a copy-constructor so I can not safely and easily capture it into c++ threads, lambdas and AsyncWorker's with pass by value. The provided example at the bottom of "https://github.com/nodejs/node-addon-api/blob/master/doc/threadsafe_function.md" solves this by having ThreadSafeCallback as a global mutable variable but this is dangerous (might break with repeated calls to the native function quickly after each other) and I also personally think global mutable variables is a bad thing. Instead the native method should initialize the ThreadSafeCallback object which is than copied into the thread/lambda/worker by value (before original object is destroyed as it goes out of scope when function returns etc).
2) FIXED BY ABOVE: In the absence of a copy-constructor, it is a problem that the ThreadSafeCallback class has only factory methods (for parameters) and lacks a constructor with the various parameters so new/delete could be used to control the life-cycle and hereby enable capturing of a pointer to ThreadSafeFunction in c++ threads, workers and lambdas (As a temporary fix, I have created by own simple wrapper class that holds a ThreadSafeFunction inside and has a constructor with all the arguments thus enabling the wrapper with the ThreadSafeFunction to be created on the heap).
3) It is not clear what initialThreadCount should be set to and how and when Acquire and Release should be called. The example sets initialThreadCount to 1 though used by two threads and does not call Acquire ? From my own experiments, it seems important to call Release exactly once to make sure the node process terminates - it does not seem to matter what Thread I call Release from in my example as long as I don't call it twice (in which case an Assert error with a nice stack trace will be shown).
4 There is no way for the C++ code to wait for the queue to be empty (all calls in queue to be processed). This would be useful to delay cleanup until a NonBlockingCall has been fully executed.
The text was updated successfully, but these errors were encountered: