mika-fischer / napi-thread-safe-callback Goto Github PK
View Code? Open in Web Editor NEWC++ utility class to perform callbacks into JavaScript from any thread
C++ utility class to perform callbacks into JavaScript from any thread
An electron application which uses @abandoneware/noble (and noble itself uses this napi-thread-safe-callback) crashes when an application exits on OSX Big Sur.
Here is a issue reported in noble repository: abandonware/noble#215
I've submitted a PR which uses thread-safe-function instead, but a maintainer of noble wants to be fixed in napi-thread-safe-callback: abandonware/noble#219 (comment)
So, I've opened this issue. How do you think?
How can I save the context of calling the js function inside my add-on, so that I can call it inside the add-on side of the c ++ function?
Thank you for the class ThreadSafeCallback
, it works fine. I'd need something similar to create a Napi::Promise::Deferred
on the main thread, but then resolve or reject it from another thread. Is it possible?
Hi, I found this package actually use libuv directly, and the N-API guide said I should stick with napi.h.
Excellent works anyway!!
Hello, first thank you for publishing this module. I am trying to call the emit function on a ObjectWrapped class that inherits from EventEmitter, in which i am passing to ThreadSafeCallback the emit function. Stepping through the code I can see the cb->call(...) is getting called but the event is never making it back to the javascript side. Below is the code in question. Any help is welcome, thank you.
Napi::Value
Signer::ReadForSignature(const CallbackInfo& info)
{
vector<int> opts =
AssertCallbackInfo(info, { { 0, { nullopt, option(napi_number) } } });
if (opts[0] == 1) {
signer->SetSignatureSize(info[0].As<Number>().Uint32Value());
} else {
signer->SetSignatureSize(4096);
}
auto emit = this->Value().Get("emit").As<Function>(); // <-- get the emit fn
auto cb = make_shared<ThreadSafeCallback>(emit); // <-- pass emit to threadsafecallback
field->SetSignature(*signer->GetSignatureBeacon());
doc.WriteUpdate(signer.get(), !output.empty());
if (!signer->HasSignaturePosition()) {
Error::New(info.Env(),
"Cannot find signature position in the document data")
.ThrowAsJavaScriptException();
return {};
}
signer->AdjustByteRange();
signer->Seek(0);
auto shareSigner = signer.get();
thread([cb, shareSigner] {
size_t sigBuffer = 65535 * 2, sigBufferLen;
char* sigData;
while (static_cast<void>(sigData = reinterpret_cast<char*>(
malloc(sizeof(char) * sigBuffer))),
!sigData) {
sigBuffer = sigBuffer / 2;
if (!sigBuffer)
break;
}
if (!sigData) {
cb->call([](Napi::Env env, vector<napi_value>& args) {
args = { String::New(env, "error"), String::New(env, "out of memory") };
});
return;
}
while (sigBufferLen = shareSigner->ReadForSignature(sigData, sigBuffer),
sigBufferLen > 0) {
cb->call([sigData, sigBuffer](Napi::Env env, vector<napi_value>& args) {
args = { String::New(env, "data"),
Buffer<char>::Copy(env, sigData, sigBuffer) };
});
}
free(sigData);
cb->call([](Napi::Env env, vector<napi_value>& args) {
args = { String::New(env, "end"), env.Undefined() };
});
})
.detach();
return this->Value();
}
....
let signer = new npdf.Signer(doc, signedPath)
signer.signatureField = field
let buf: Buffer
signer.readForSignature() // .on funcs never are invoked
signer.on('data', chunk => {
buf = Buffer.concat(chunk)
})
signer.on('end', () => {
console.log(buf.length)
return resolve()
})
signer.on('error', e => {
console.log(e)
return reject(e)
})
Please write a CMakeLists.txt file for building this project.
Hi,
i have builld fail o with [email protected] ([email protected]).
napi-thread-safe-callback-impl.hpp(183): error C2668: 'ThreadSafeCallback::operator ()': ambiguous call to overloaded function
On [email protected] code compiles as expected.
Hi
I execute a ThreadSafeCallback repeatedly with a streaming data. But in windows environment it execute only once, the cpp function calls repeatedly but ThreadSafeCallback execute only once.
In mac environment this has no issues.
`
class Callback {
std::shared_ptr<ThreadSafeCallback> callback;
Napi::Value runGStreamer(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
callback = std::make_shared<ThreadSafeCallback>(info[0].As<Function>());
}
// Calls from a boost thread, calls each time it has data in a stream infinitely
void hasData(Data &data) {
printf("has data\n"); // <- this get calls repeatedly
// But below execute only once
callback->call([data](Env env, std::vector<napi_value>& args) {
args = { Napi::Number::New(env, data.size) };
});
}
}
`
What am i missing?
Hi,
I'm creating a wrapper for a library that has "pumping" mode for events.
In this mode, lib calls lot's of callbacks.
It looks like when nodejs is busy with something synchronous like "console.log()", callback can't make it with error:
Assertion failed: !(handle->flags & UV__HANDLE_CLOSING), file src\win\async.c, line 76
npm ERR! code ELIFECYCLE
npm ERR! errno 3221226505
Should be easy to reproduce in tests by calling callback multiple times in a loop while doing something synchronous in nodejs.
Could you please try to reproduce this issue?
In case it's a known limitation, what workaround options are available?
Thank you
Hi,
I've been looking for a thread-safe implementation for a while, thanks for this!
I've tried copy pasting the example_async_work into my code (c++ and js), but I can't get the callback to work,
It enters the thread but the callback never gets called.
The only difference with your code is that I've made the function part of a class instead of being standalone.
If I run your tests they work fine, so I'm not sure what the issue is.
Need to mark void ThreadSafeCallback::unref
as inline, otherwise there are duplicate definition errors that could appear if you include the headers in different files.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.