-
Notifications
You must be signed in to change notification settings - Fork 461
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
Ability to get reference counter value from Napi::Reference object #702
Comments
There was not specific reason, other than we did not think of it as requirement. What is your use case for it? |
I want to use ref counter for detecting if there are no active workers for some object. Consider some class with asynchronous methods: class Foo {
foo(): Promise<void>;
bar(): Promise<void>;
dispose(): Promise<void>;
} Each async method increases ref counter for class Foo : public Napi::ObjectWrap<Foo> {
// ...
};
class DisposeWorker : public Napi::AsyncWorker {
// ...
};
Napi::Value Foo::Dispose(const Napi::CallbackInfo& info) {
if (RefCount() > 0) {
// Execute worker in future when ref count will be equal to 0.
pending_dispose_worker_ = new DisposeWorker();
return;
}
// Call worker immediately.
auto worker = new DisposeWorker();
worker->Queue();
} |
@ikokostya if you want to execute some code when a certain |
@ikokostya something like this might work: class Foo: public Napi::ObjectWrap<Foo> {
public:
Foo(const Napi::FunctionCallbackInfo& info) {
auto worker = new DisposeWorker();
info
.This()
.As<Napi::Object>()
.AddFinalizer([](Napi::Env env, DisposeWorker* worker) {
worker->Queue();
}, worker);
}
}; |
@gabrielschulhof I have another use case. The dispose worker calls non-trivial destructor on the corresponding native object: class DisposeWorker : public AsyncWorker {
public:
DisposeWorker(Napi::Env env, Foo* foo) : AsyncWorker(env), foo_(foo) {
foo_->Ref();
}
~DisposeWorker() {
foo_->Unref();
}
protected:
void Execute() override {
foo_->native_handle.release(); // where native_handle is std::unique_ptr<NativeFoo>
}
private:
Foo* foo_;
}; When dispose will be called from JavaScript await foo.dispose(); I cannot just queue new worker auto worker = new DisposeWorker(info.Env(), this);
worker->Queue(); because there may exist another worker threads on the native object. Instead, I need to wait while other worker threads will be executed before start the dispose worker.
|
Should finalizer always be called before napi_get_reference_value starts returning null for result? I'm seeing occasions where my finalizer gets called later, meaning Reference#Value() is throwing an Invalid Argument exception. |
I don't believe there is any guarantee as to when the finalizer will be called except that it will be sometime after the object is collected. This means it is reasonable for napi_get_reference_value to return NULL before the finalizer is run. Do you have a small recreate? The code in Value checks if the |
I can try to get a small recreate. But in the meantime I believe the problem to be that |
@mhdawson I got a small repro.
|
Thanks, I've created a test we can add to our test suite and am looking at how we should fix. |
Fixes: nodejs#702 Previously calling Value() on a Reference for a TypedArray that the enderlying object had been collected would result in an error due to a failure in creating the return value. Signed-off-by: Michael Dawson <michael_dawson@ca.ibm.com>
@davedoesdev can you check out the fix in #726. Note that you will need to call IsEmpty() on the value after getting it back from weak.Value() to check if the value was returned or not. The weak.IsEmpty() does not check if the underlying object is present or not just if the weak itself wraps a N-API reference. |
Yep, works for me - thanks! |
I solved my original problem without |
Oops, missed that there is open associated PR |
Fixes: nodejs/node-addon-api#702 Previously calling Value() on a Reference for a TypedArray that the enderlying object had been collected would result in an error due to a failure in creating the return value. Signed-off-by: Michael Dawson <michael_dawson@ca.ibm.com> PR-URL: nodejs/node-addon-api#726 Fixes: nodejs/node-addon-api#702 Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
Fixes: nodejs/node-addon-api#702 Previously calling Value() on a Reference for a TypedArray that the enderlying object had been collected would result in an error due to a failure in creating the return value. Signed-off-by: Michael Dawson <michael_dawson@ca.ibm.com> PR-URL: nodejs/node-addon-api#726 Fixes: nodejs/node-addon-api#702 Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
Fixes: nodejs/node-addon-api#702 Previously calling Value() on a Reference for a TypedArray that the enderlying object had been collected would result in an error due to a failure in creating the return value. Signed-off-by: Michael Dawson <michael_dawson@ca.ibm.com> PR-URL: nodejs/node-addon-api#726 Fixes: nodejs/node-addon-api#702 Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
Fixes: nodejs/node-addon-api#702 Previously calling Value() on a Reference for a TypedArray that the enderlying object had been collected would result in an error due to a failure in creating the return value. Signed-off-by: Michael Dawson <michael_dawson@ca.ibm.com> PR-URL: nodejs/node-addon-api#726 Fixes: nodejs/node-addon-api#702 Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
There is no way to get reference count value from
Napi::Reference
object without side effects. I can use onlyRef()
orUnref()
method, which returns the resulting reference count value.What is the reason to not export this functionality as public API?
The text was updated successfully, but these errors were encountered: