Skip to content

Commit

Permalink
refactor(Worklets): move UIScheduler (#6789)
Browse files Browse the repository at this point in the history
<!-- Thanks for submitting a pull request! We appreciate you spending
the time to work on these changes. Please follow the template so that
the reviewers can easily understand what the code changes affect. -->

## Summary

This pull requests moves `UIScheduler`, a class responsible for
scheduling operations to the Main Thread, to Worklets. While it seems
that `Reanimated` should have some freedom scheduling to the Main Thread
if it doesn't use the UI Runtime, I think it's better to move it now as
is and add some secondary APIs later on. We'll have a better overview of
what we need once more code is moved to Worklets.

## Test plan

- CI
- [x] Working 0.76 Paper/Fabric iOS/Android
  • Loading branch information
tjzel authored Dec 10, 2024
1 parent 2a947a8 commit 17e89ca
Show file tree
Hide file tree
Showing 24 changed files with 84 additions and 80 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,13 @@ ReanimatedModuleProxy::ReanimatedModuleProxy(
const std::shared_ptr<WorkletsModuleProxy> &workletsModuleProxy,
jsi::Runtime &rnRuntime,
const std::shared_ptr<CallInvoker> &jsCallInvoker,
const std::shared_ptr<UIScheduler> &uiScheduler,
const PlatformDepMethodsHolder &platformDepMethodsHolder,
const bool isBridgeless,
const bool isReducedMotion)
: ReanimatedModuleProxySpec(jsCallInvoker),
isBridgeless_(isBridgeless),
isReducedMotion_(isReducedMotion),
workletsModuleProxy_(workletsModuleProxy),
uiScheduler_(uiScheduler),
valueUnpackerCode_(workletsModuleProxy->getValueUnpackerCode()),
uiWorkletRuntime_(std::make_shared<WorkletRuntime>(
rnRuntime,
Expand Down Expand Up @@ -207,7 +205,7 @@ void ReanimatedModuleProxy::scheduleOnUI(
const jsi::Value &worklet) {
auto shareableWorklet = extractShareableOrThrow<ShareableWorklet>(
rt, worklet, "[Reanimated] Only worklets can be scheduled to run on UI.");
uiScheduler_->scheduleOnUI(COPY_CAPTURE_WITH_THIS {
workletsModuleProxy_->getUIScheduler()->scheduleOnUI(COPY_CAPTURE_WITH_THIS {
#if JS_RUNTIME_HERMES
// JSI's scope defined here allows for JSI-objects to be cleared up
// after each runtime loop. Within these loops we typically create some
Expand Down Expand Up @@ -264,7 +262,7 @@ jsi::Value ReanimatedModuleProxy::registerEventHandler(
rt, worklet, "[Reanimated] Event handler must be a worklet.");
int emitterReactTagInt = emitterReactTag.asNumber();

uiScheduler_->scheduleOnUI(COPY_CAPTURE_WITH_THIS {
workletsModuleProxy_->getUIScheduler()->scheduleOnUI(COPY_CAPTURE_WITH_THIS {
auto handler = std::make_shared<WorkletEventHandler>(
newRegistrationId, eventNameStr, emitterReactTagInt, handlerShareable);
eventHandlerRegistry_->registerEventHandler(std::move(handler));
Expand All @@ -277,7 +275,7 @@ void ReanimatedModuleProxy::unregisterEventHandler(
jsi::Runtime &,
const jsi::Value &registrationId) {
uint64_t id = registrationId.asNumber();
uiScheduler_->scheduleOnUI(
workletsModuleProxy_->getUIScheduler()->scheduleOnUI(
COPY_CAPTURE_WITH_THIS

{ eventHandlerRegistry_->unregisterEventHandler(id); });
Expand Down Expand Up @@ -349,7 +347,7 @@ jsi::Value ReanimatedModuleProxy::getViewProp(
const auto funPtr = std::make_shared<jsi::Function>(
callback.getObject(rnRuntime).asFunction(rnRuntime));
const auto shadowNode = shadowNodeFromValue(rnRuntime, shadowNodeWrapper);
uiScheduler_->scheduleOnUI(COPY_CAPTURE_WITH_THIS {
workletsModuleProxy_->getUIScheduler()->scheduleOnUI(COPY_CAPTURE_WITH_THIS {
jsi::Runtime &uiRuntime = uiWorkletRuntime_->getJSIRuntime();
const auto resultStr =
obtainPropFromShadowNode(uiRuntime, propNameStr, shadowNode);
Expand Down Expand Up @@ -377,7 +375,7 @@ jsi::Value ReanimatedModuleProxy::getViewProp(

const int viewTagInt = viewTag.asNumber();

uiScheduler_->scheduleOnUI(
workletsModuleProxy_->getUIScheduler()->scheduleOnUI(
COPY_CAPTURE_WITH_THIS

() {
Expand Down Expand Up @@ -859,7 +857,7 @@ void ReanimatedModuleProxy::initializeLayoutAnimationsProxy() {
componentDescriptorRegistry,
scheduler->getContextContainer(),
uiWorkletRuntime_->getJSIRuntime(),
uiScheduler_);
workletsModuleProxy_->getUIScheduler());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ class ReanimatedModuleProxy : public ReanimatedModuleProxySpec {
const std::shared_ptr<WorkletsModuleProxy> &workletsModuleProxy,
jsi::Runtime &rnRuntime,
const std::shared_ptr<CallInvoker> &jsCallInvoker,
const std::shared_ptr<UIScheduler> &uiScheduler,
const PlatformDepMethodsHolder &platformDepMethodsHolder,
const bool isBridgeless,
const bool isReducedMotion);
Expand Down Expand Up @@ -194,7 +193,6 @@ class ReanimatedModuleProxy : public ReanimatedModuleProxySpec {
const bool isBridgeless_;
const bool isReducedMotion_;
const std::shared_ptr<WorkletsModuleProxy> workletsModuleProxy_;
const std::shared_ptr<UIScheduler> uiScheduler_;
const std::string valueUnpackerCode_;
std::shared_ptr<WorkletRuntime> uiWorkletRuntime_;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,13 @@ WorkletsModuleProxy::WorkletsModuleProxy(
const std::string &valueUnpackerCode,
const std::shared_ptr<MessageQueueThread> &jsQueue,
const std::shared_ptr<CallInvoker> &jsCallInvoker,
const std::shared_ptr<JSScheduler> &jsScheduler)
const std::shared_ptr<JSScheduler> &jsScheduler,
const std::shared_ptr<UIScheduler> &uiScheduler)
: WorkletsModuleProxySpec(jsCallInvoker),
valueUnpackerCode_(valueUnpackerCode),
jsQueue_(jsQueue),
jsScheduler_(jsScheduler) {}
jsScheduler_(jsScheduler),
uiScheduler_(uiScheduler) {}

WorkletsModuleProxy::~WorkletsModuleProxy() {}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <worklets/NativeModules/WorkletsModuleProxySpec.h>
#include <worklets/Tools/JSScheduler.h>
#include <worklets/Tools/SingleInstanceChecker.h>
#include <worklets/Tools/UIScheduler.h>
#include <worklets/WorkletRuntime/WorkletRuntime.h>
#include <memory>
#include <string>
Expand All @@ -16,7 +17,8 @@ class WorkletsModuleProxy : public WorkletsModuleProxySpec {
const std::string &valueUnpackerCode,
const std::shared_ptr<MessageQueueThread> &jsQueue,
const std::shared_ptr<CallInvoker> &jsCallInvoker,
const std::shared_ptr<JSScheduler> &jsScheduler);
const std::shared_ptr<JSScheduler> &jsScheduler,
const std::shared_ptr<UIScheduler> &uiScheduler);

~WorkletsModuleProxy();

Expand All @@ -38,10 +40,15 @@ class WorkletsModuleProxy : public WorkletsModuleProxySpec {
return jsScheduler_;
}

[[nodiscard]] inline std::shared_ptr<UIScheduler> getUIScheduler() const {
return uiScheduler_;
}

private:
const std::string valueUnpackerCode_;
const std::shared_ptr<MessageQueueThread> jsQueue_;
const std::shared_ptr<JSScheduler> jsScheduler_;
const std::shared_ptr<UIScheduler> uiScheduler_;
#ifndef NDEBUG
SingleInstanceChecker<WorkletsModuleProxy> singleInstanceChecker_;
#endif // NDEBUG
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ public class NativeProxy extends NativeProxyCommon {
workletsModule,
Objects.requireNonNull(context.getJavaScriptContextHolder()).get(),
callInvokerHolder,
mAndroidUIScheduler,
LayoutAnimations,
context.isBridgeless(),
fabricUIManager);
Expand All @@ -58,7 +57,6 @@ private native HybridData initHybrid(
WorkletsModule workletsModule,
long jsContext,
CallInvokerHolderImpl jsCallInvokerHolder,
AndroidUIScheduler androidUIScheduler,
LayoutAnimations LayoutAnimations,
boolean isBridgeless,
FabricUIManager fabricUIManager);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
#include <reanimated/LayoutAnimations/LayoutAnimationsManager.h>
#include <reanimated/RuntimeDecorators/RNRuntimeDecorator.h>
#include <reanimated/Tools/PlatformDepMethodsHolder.h>
#include <reanimated/android/AndroidUIScheduler.h>
#include <reanimated/android/NativeProxy.h>

#include <worklets/Tools/ReanimatedJSIUtils.h>
#include <worklets/Tools/ReanimatedVersion.h>
#include <worklets/WorkletRuntime/ReanimatedRuntime.h>
#include <worklets/WorkletRuntime/WorkletRuntime.h>
#include <worklets/WorkletRuntime/WorkletRuntimeCollector.h>
#include <worklets/android/AndroidUIScheduler.h>

#include <android/log.h>
#include <fbjni/fbjni.h>
Expand All @@ -31,7 +31,6 @@ NativeProxy::NativeProxy(
const std::shared_ptr<WorkletsModuleProxy> &workletsModuleProxy,
jsi::Runtime *rnRuntime,
const std::shared_ptr<facebook::react::CallInvoker> &jsCallInvoker,
const std::shared_ptr<UIScheduler> &uiScheduler,
jni::global_ref<LayoutAnimations::javaobject> layoutAnimations,
const bool isBridgeless
#ifdef RCT_NEW_ARCH_ENABLED
Expand All @@ -46,7 +45,6 @@ NativeProxy::NativeProxy(
workletsModuleProxy,
*rnRuntime,
jsCallInvoker,
uiScheduler,
getPlatformDependentMethods(),
isBridgeless,
getIsReducedMotion())),
Expand Down Expand Up @@ -91,7 +89,6 @@ jni::local_ref<NativeProxy::jhybriddata> NativeProxy::initHybrid(
jlong jsContext,
jni::alias_ref<facebook::react::CallInvokerHolder::javaobject>
jsCallInvokerHolder,
jni::alias_ref<AndroidUIScheduler::javaobject> androidUiScheduler,
jni::alias_ref<LayoutAnimations::javaobject> layoutAnimations,
bool isBridgeless
#ifdef RCT_NEW_ARCH_ENABLED
Expand All @@ -101,14 +98,12 @@ jni::local_ref<NativeProxy::jhybriddata> NativeProxy::initHybrid(
#endif
) {
auto jsCallInvoker = jsCallInvokerHolder->cthis()->getCallInvoker();
auto uiScheduler = androidUiScheduler->cthis()->getUIScheduler();
auto workletsModuleProxy = jWorkletsModule->cthis()->getWorkletsModuleProxy();
return makeCxxInstance(
jThis,
workletsModuleProxy,
(jsi::Runtime *)jsContext,
jsCallInvoker,
uiScheduler,
make_global(layoutAnimations),
isBridgeless
#ifdef RCT_NEW_ARCH_ENABLED
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
#pragma once

#include <reanimated/NativeModules/ReanimatedModuleProxy.h>
#include <reanimated/android/AndroidUIScheduler.h>
#include <reanimated/android/JNIHelper.h>
#include <reanimated/android/LayoutAnimations.h>

#include <worklets/Tools/UIScheduler.h>
#include <worklets/android/WorkletsModule.h>

#include <ReactCommon/CallInvokerHolder.h>
Expand Down Expand Up @@ -153,7 +151,6 @@ class NativeProxy : public jni::HybridClass<NativeProxy> {
jlong jsContext,
jni::alias_ref<facebook::react::CallInvokerHolder::javaobject>
jsCallInvokerHolder,
jni::alias_ref<AndroidUIScheduler::javaobject> androidUiScheduler,
jni::alias_ref<LayoutAnimations::javaobject> layoutAnimations,
const bool isBridgeless
#ifdef RCT_NEW_ARCH_ENABLED
Expand Down Expand Up @@ -268,7 +265,6 @@ class NativeProxy : public jni::HybridClass<NativeProxy> {
const std::shared_ptr<WorkletsModuleProxy> &workletsModuleProxy,
jsi::Runtime *rnRuntime,
const std::shared_ptr<facebook::react::CallInvoker> &jsCallInvoker,
const std::shared_ptr<UIScheduler> &uiScheduler,
jni::global_ref<LayoutAnimations::javaobject> layoutAnimations,
const bool isBridgeless
#ifdef RCT_NEW_ARCH_ENABLED
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#include <fbjni/fbjni.h>

#include <reanimated/android/AndroidUIScheduler.h>
#include <reanimated/android/LayoutAnimations.h>
#include <reanimated/android/NativeProxy.h>

Expand All @@ -9,7 +8,6 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
reanimated::NativeProxy::registerNatives();
reanimated::AnimationFrameCallback::registerNatives();
reanimated::EventHandler::registerNatives();
reanimated::AndroidUIScheduler::registerNatives();
reanimated::LayoutAnimations::registerNatives();
reanimated::SensorSetter::registerNatives();
reanimated::KeyboardWorkletWrapper::registerNatives();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#include <reanimated/android/AndroidUIScheduler.h>
#include <worklets/android/AndroidUIScheduler.h>

#include <android/log.h>
#include <fbjni/fbjni.h>
#include <jsi/jsi.h>

namespace reanimated {
namespace worklets {

using namespace facebook;
using namespace react;
Expand Down Expand Up @@ -57,4 +57,4 @@ void AndroidUIScheduler::registerNatives() {
});
}

} // namespace reanimated
} // namespace worklets
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@

#include <memory>

namespace reanimated {
namespace worklets {

using namespace facebook;
using namespace worklets;

class AndroidUIScheduler : public jni::HybridClass<AndroidUIScheduler> {
public:
static auto constexpr kJavaDescriptor =
"Lcom/swmansion/reanimated/AndroidUIScheduler;";
"Lcom/swmansion/worklets/AndroidUIScheduler;";
static jni::local_ref<jhybriddata> initHybrid(
jni::alias_ref<jhybridobject> jThis);
static void registerNatives();
Expand All @@ -41,4 +41,4 @@ class AndroidUIScheduler : public jni::HybridClass<AndroidUIScheduler> {
jni::alias_ref<AndroidUIScheduler::jhybridobject> jThis);
};

} // namespace reanimated
} // namespace worklets
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,16 @@ WorkletsModule::WorkletsModule(
const std::string &valueUnpackerCode,
jni::alias_ref<JavaMessageQueueThread::javaobject> messageQueueThread,
const std::shared_ptr<facebook::react::CallInvoker> &jsCallInvoker,
const std::shared_ptr<worklets::JSScheduler> &jsScheduler)
const std::shared_ptr<worklets::JSScheduler> &jsScheduler,
const std::shared_ptr<UIScheduler> &uiScheduler)
: javaPart_(jni::make_global(jThis)),
rnRuntime_(rnRuntime),
workletsModuleProxy_(std::make_shared<WorkletsModuleProxy>(
valueUnpackerCode,
std::make_shared<JMessageQueueThread>(messageQueueThread),
jsCallInvoker,
jsScheduler)) {
jsScheduler,
uiScheduler)) {
RNRuntimeWorkletDecorator::decorate(*rnRuntime_, workletsModuleProxy_);
}

Expand All @@ -40,18 +42,22 @@ jni::local_ref<WorkletsModule::jhybriddata> WorkletsModule::initHybrid(
const std::string &valueUnpackerCode,
jni::alias_ref<JavaMessageQueueThread::javaobject> messageQueueThread,
jni::alias_ref<facebook::react::CallInvokerHolder::javaobject>
jsCallInvokerHolder) {
jsCallInvokerHolder,
jni::alias_ref<worklets::AndroidUIScheduler::javaobject>
androidUIScheduler) {
auto jsCallInvoker = jsCallInvokerHolder->cthis()->getCallInvoker();
auto rnRuntime = reinterpret_cast<jsi::Runtime *>(jsContext);
auto jsScheduler =
std::make_shared<worklets::JSScheduler>(*rnRuntime, jsCallInvoker);
auto uiScheduler = androidUIScheduler->cthis()->getUIScheduler();
return makeCxxInstance(
jThis,
rnRuntime,
valueUnpackerCode,
messageQueueThread,
jsCallInvoker,
jsScheduler);
jsScheduler,
uiScheduler);
}

void WorkletsModule::registerNatives() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <react/jni/WritableNativeMap.h>

#include <worklets/NativeModules/WorkletsModuleProxy.h>
#include <worklets/android/AndroidUIScheduler.h>

#include <memory>
#include <string>
Expand All @@ -34,7 +35,9 @@ class WorkletsModule : public jni::HybridClass<WorkletsModule> {
const std::string &valueUnpackerCode,
jni::alias_ref<JavaMessageQueueThread::javaobject> messageQueueThread,
jni::alias_ref<facebook::react::CallInvokerHolder::javaobject>
jsCallInvokerHolder);
jsCallInvokerHolder,
jni::alias_ref<worklets::AndroidUIScheduler::javaobject>
androidUIScheduler);

static void registerNatives();

Expand All @@ -54,7 +57,8 @@ class WorkletsModule : public jni::HybridClass<WorkletsModule> {
const std::string &valueUnpackerCode,
jni::alias_ref<JavaMessageQueueThread::javaobject> messageQueueThread,
const std::shared_ptr<facebook::react::CallInvoker> &jsCallInvoker,
const std::shared_ptr<worklets::JSScheduler> &jsScheduler);
const std::shared_ptr<worklets::JSScheduler> &jsScheduler,
const std::shared_ptr<UIScheduler> &uiScheduler);
};

} // namespace worklets
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
#include <fbjni/fbjni.h>

#include <worklets/android/AndroidUIScheduler.h>
#include <worklets/android/WorkletsModule.h>

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
return facebook::jni::initialize(
vm, [] { worklets::WorkletsModule::registerNatives(); });
return facebook::jni::initialize(vm, [] {
worklets::WorkletsModule::registerNatives();
worklets::AndroidUIScheduler::registerNatives();
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -128,14 +128,13 @@ public void invalidate() {
}

if (mNativeProxy != null) {
mNativeProxy.invalidate();
mNativeProxy = null;
}
}

public void initWithContext(ReactApplicationContext reactApplicationContext) {
mNativeProxy = new NativeProxy(reactApplicationContext, mWorkletsModule);
mAnimationManager.setAndroidUIScheduler(getNativeProxy().getAndroidUIScheduler());
mAnimationManager.setAndroidUIScheduler(mWorkletsModule.getAndroidUIScheduler());
compatibility = new ReaCompatibility(reactApplicationContext);
compatibility.registerFabricEventListener(this);
}
Expand Down
Loading

0 comments on commit 17e89ca

Please sign in to comment.