-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
refactor: explicit invalidations for native and cpp #6850
base: main
Are you sure you want to change the base?
Conversation
explicit WorkletsModule( | ||
jni::alias_ref<WorkletsModule::jhybridobject> jThis, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Turns out we don't need to keep the reference to Java part of WorkletsModule
in cpp.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it still have to be a HybridClass
or can we convert it back to JavaClass
or something?
assertWithMessage( | ||
instanceCount_ <= 1, | ||
instanceCount_ < 1, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When cleaning during invalidation stage, it shouldn't be possible for two instances to exist at the same time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not just instanceCount_ == 0
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The changes look good to me, I left some remarks in the comments. Two more general questions:
- Why do we need a separate
invalidate
method? Why can't we just clear the pointers in C++ destructors like we used to do? - Once
invalidate
method is called, shall we add some assertions to prevent us from calling any methods of an invalidated object? - Why can't we just use weak pointers to store
WorkletsModule
inReanimatedModule
? This way there's no strong link between those two.
assertWithMessage( | ||
instanceCount_ <= 1, | ||
instanceCount_ < 1, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not just instanceCount_ == 0
?
return makeCxxInstance( | ||
jThis, | ||
rnRuntime, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change looks weird, do we really need WorkletsModule
to be a Hybrid class if we don't use jThis
here in makeCxxInstance
?
// We have to destroy extra runtimes when invalidate is called. If we clean | ||
// it up later instead there's a chance the runtime will retain references | ||
// to invalidated memory and will crash on destruction. | ||
workletsModuleProxy_.reset(); | ||
[super invalidate]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's add a newline here since [super invalidate];
is unrelated to the comment above.
// We have to destroy extra runtimes when invalidate is called. If we clean | |
// it up later instead there's a chance the runtime will retain references | |
// to invalidated memory and will crash on destruction. | |
workletsModuleProxy_.reset(); | |
[super invalidate]; | |
// We have to destroy extra runtimes when invalidate is called. If we clean | |
// it up later instead there's a chance the runtime will retain references | |
// to invalidated memory and will crash on destruction. | |
workletsModuleProxy_.reset(); | |
[super invalidate]; |
// We have to destroy extra runtimes when invalidate is called. If we clean | ||
// it up later instead there's a chance the runtime will retain references | ||
// to invalidated memory and will crash on its destruction. | ||
invalidateCpp(); | ||
mAndroidUIScheduler.deactivate(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's add a newline here as well
// We have to destroy extra runtimes when invalidate is called. If we clean | |
// it up later instead there's a chance the runtime will retain references | |
// to invalidated memory and will crash on its destruction. | |
invalidateCpp(); | |
mAndroidUIScheduler.deactivate(); | |
// We have to destroy extra runtimes when invalidate is called. If we clean | |
// it up later instead there's a chance the runtime will retain references | |
// to invalidated memory and will crash on its destruction. | |
invalidateCpp(); | |
mAndroidUIScheduler.deactivate(); |
explicit WorkletsModule( | ||
jni::alias_ref<WorkletsModule::jhybridobject> jThis, | ||
jsi::Runtime *rnRuntime, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If possible, let's pass the runtime as a reference instead of a pointer, i.e. jsi::Runtime &
.
void invalidateCpp(); | ||
|
||
friend HybridBase; | ||
jsi::Runtime *rnRuntime_; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If possible, let's store runtime as a reference.
jsi::Runtime *rnRuntime_; | |
jsi::Runtime &rnRuntime_; |
explicit WorkletsModule( | ||
jni::alias_ref<WorkletsModule::jhybridobject> jThis, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it still have to be a HybridClass
or can we convert it back to JavaClass
or something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you elaborate more on why performing cleanup in the C++ destructor is considered too late? This isn't entirely clear to me, but it seems to be important.
Summary
This pull requests refactors memory management of Worklets and Reanimated.
Basically, since Reanimated can obtain WorkletsModuleProxy and the Worklet Runtimes as shared pointers, it has to release them explicitly during the invalidation stage of Native Modules. Releasing them later on (e.g. via deconstructors) might lead into issues and crashes.
Ideally we'd instead use some different solution here than shared pointers, but it can wait as it's not mandatory at the moment and could be a significant refactor.
Fixes:
Test plan