Skip to content

Commit 8041df8

Browse files
RSNarafacebook-github-bot
authored andcommitted
RuntimeExecutor: Fork an ios implementation
Differential Revision: D74901907
1 parent ba092bf commit 8041df8

File tree

10 files changed

+221
-75
lines changed

10 files changed

+221
-75
lines changed

packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler_Legacy.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "RuntimeScheduler_Legacy.h"
99
#include "SchedulerPriorityUtils.h"
1010

11+
#include <ReactCommon/RuntimeExecutorUtils.h>
1112
#include <cxxreact/TraceSection.h>
1213
#include <react/renderer/consistency/ScopedShadowTreeRevisionLock.h>
1314
#include <utility>

packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler_Modern.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "RuntimeScheduler_Modern.h"
99
#include "SchedulerPriorityUtils.h"
1010

11+
#include <ReactCommon/RuntimeExecutorUtils.h>
1112
#include <cxxreact/TraceSection.h>
1213
#include <jsinspector-modern/tracing/EventLoopReporter.h>
1314
#include <react/featureflags/ReactNativeFeatureFlags.h>

packages/react-native/ReactCommon/react/runtime/BufferedRuntimeExecutor.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <ReactCommon/RuntimeExecutor.h>
1111
#include <jsi/jsi.h>
1212
#include <atomic>
13+
#include <mutex>
1314
#include <queue>
1415

1516
namespace facebook::react {

packages/react-native/ReactCommon/runtimeexecutor/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ set(CMAKE_VERBOSE_MAKEFILE on)
88

99
include(${REACT_COMMON_DIR}/cmake-utils/react-native-flags.cmake)
1010

11-
file(GLOB_RECURSE runtimeexecutor_SRC CONFIGURE_DEPENDS *.cpp *.h)
11+
file(GLOB_RECURSE runtimeexecutor_SRC CONFIGURE_DEPENDS *.cpp *.h ${CMAKE_CURRENT_SOURCE_DIR}/platform/android/*.cpp)
1212

1313
add_library(runtimeexecutor OBJECT ${runtimeexecutor_SRC})
1414

15-
target_include_directories(runtimeexecutor PUBLIC .)
15+
target_include_directories(runtimeexecutor PUBLIC . ${CMAKE_CURRENT_SOURCE_DIR}/platform/android/)
1616

1717
target_link_libraries(runtimeexecutor jsi)
1818
target_compile_reactnative_options(runtimeexecutor PRIVATE)

packages/react-native/ReactCommon/runtimeexecutor/React-runtimeexecutor.podspec

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ else
1717
end
1818

1919
Pod::Spec.new do |s|
20+
source_files = "*.{m,mm,cpp,h}", "platform/ios/**/*.{m,mm,cpp,h}"
21+
2022
s.name = "React-runtimeexecutor"
2123
s.version = version
2224
s.summary = "-" # TODO
@@ -25,8 +27,14 @@ Pod::Spec.new do |s|
2527
s.author = "Meta Platforms, Inc. and its affiliates"
2628
s.platforms = min_supported_versions
2729
s.source = source
28-
s.source_files = "**/*.{cpp,h}"
30+
s.source_files = source_files
2931
s.header_dir = "ReactCommon"
3032

33+
if ENV['USE_FRAMEWORKS']
34+
s.module_name = "React-runtimeexecutor"
35+
s.header_mappings_dir = "."
36+
header_search_paths = header_search_paths + ["\"$(PODS_TARGET_SRCROOT)/platform/ios\""]
37+
end
38+
3139
s.dependency "React-jsi", version
3240
end

packages/react-native/ReactCommon/runtimeexecutor/ReactCommon/RuntimeExecutor.h

Lines changed: 0 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,6 @@
77

88
#pragma once
99

10-
#include <mutex>
11-
#include <thread>
12-
1310
#include <jsi/jsi.h>
1411

1512
namespace facebook::react {
@@ -25,73 +22,4 @@ namespace facebook::react {
2522
using RuntimeExecutor =
2623
std::function<void(std::function<void(jsi::Runtime& runtime)>&& callback)>;
2724

28-
/*
29-
* Executes a `callback` in a *synchronous* manner on the same thread using
30-
* given `RuntimeExecutor`.
31-
* Use this method when the caller needs to *be blocked* by executing the
32-
* `callback` and requires that the callback will be executed on the same
33-
* thread.
34-
* Example order of events (when not a sync call in runtimeExecutor callback):
35-
* - [UI thread] Lock all mutexes at start
36-
* - [UI thread] runtimeCaptured.lock before callback
37-
* - [JS thread] Set runtimePtr in runtimeExecutor callback
38-
* - [JS thread] runtimeCaptured.unlock in runtimeExecutor callback
39-
* - [UI thread] Call callback
40-
* - [JS thread] callbackExecuted.lock in runtimeExecutor callback
41-
* - [UI thread] callbackExecuted.unlock after callback
42-
* - [UI thread] jsBlockExecuted.lock after callback
43-
* - [JS thread] jsBlockExecuted.unlock in runtimeExecutor callback
44-
*/
45-
inline static void executeSynchronouslyOnSameThread_CAN_DEADLOCK(
46-
const RuntimeExecutor& runtimeExecutor,
47-
std::function<void(jsi::Runtime& runtime)>&& callback) noexcept {
48-
// Note: We need the third mutex to get back to the main thread before
49-
// the lambda is finished (because all mutexes are allocated on the stack).
50-
51-
std::mutex runtimeCaptured;
52-
std::mutex callbackExecuted;
53-
std::mutex jsBlockExecuted;
54-
55-
runtimeCaptured.lock();
56-
callbackExecuted.lock();
57-
jsBlockExecuted.lock();
58-
59-
jsi::Runtime* runtimePtr;
60-
61-
auto threadId = std::this_thread::get_id();
62-
63-
runtimeExecutor([&](jsi::Runtime& runtime) {
64-
runtimePtr = &runtime;
65-
66-
if (threadId == std::this_thread::get_id()) {
67-
// In case of a synchronous call, we should unlock mutexes and return.
68-
runtimeCaptured.unlock();
69-
jsBlockExecuted.unlock();
70-
return;
71-
}
72-
73-
runtimeCaptured.unlock();
74-
// `callback` is called somewhere here.
75-
callbackExecuted.lock();
76-
jsBlockExecuted.unlock();
77-
});
78-
79-
runtimeCaptured.lock();
80-
callback(*runtimePtr);
81-
callbackExecuted.unlock();
82-
jsBlockExecuted.lock();
83-
}
84-
85-
template <typename DataT>
86-
inline static DataT executeSynchronouslyOnSameThread_CAN_DEADLOCK(
87-
const RuntimeExecutor& runtimeExecutor,
88-
std::function<DataT(jsi::Runtime& runtime)>&& callback) noexcept {
89-
DataT data;
90-
91-
executeSynchronouslyOnSameThread_CAN_DEADLOCK(
92-
runtimeExecutor,
93-
[&](jsi::Runtime& runtime) { data = callback(runtime); });
94-
95-
return data;
96-
}
9725
} // namespace facebook::react
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#include <ReactCommon/RuntimeExecutorUtils.h>
9+
#include <mutex>
10+
#include <thread>
11+
12+
namespace facebook::react {
13+
/**
14+
* Example order of events (when not a sync call in runtimeExecutor
15+
* callback):
16+
* - [UI thread] Lock all mutexes at start
17+
* - [UI thread] runtimeCaptured.lock before callback
18+
* - [JS thread] Set runtimePtr in runtimeExecutor callback
19+
* - [JS thread] runtimeCaptured.unlock in runtimeExecutor callback
20+
* - [UI thread] Call callback
21+
* - [JS thread] callbackExecuted.lock in runtimeExecutor callback
22+
* - [UI thread] callbackExecuted.unlock after callback
23+
* - [UI thread] jsBlockExecuted.lock after callback
24+
* - [JS thread] jsBlockExecuted.unlock in runtimeExecutor callback
25+
*/
26+
void executeSynchronouslyOnSameThread_CAN_DEADLOCK(
27+
const RuntimeExecutor& runtimeExecutor,
28+
std::function<void(jsi::Runtime& runtime)>&& callback) noexcept {
29+
// Note: We need the third mutex to get back to the main thread before
30+
// the lambda is finished (because all mutexes are allocated on the stack).
31+
32+
std::mutex runtimeCaptured;
33+
std::mutex callbackExecuted;
34+
std::mutex jsBlockExecuted;
35+
36+
runtimeCaptured.lock();
37+
callbackExecuted.lock();
38+
jsBlockExecuted.lock();
39+
40+
jsi::Runtime* runtimePtr;
41+
42+
auto threadId = std::this_thread::get_id();
43+
44+
runtimeExecutor([&](jsi::Runtime& runtime) {
45+
runtimePtr = &runtime;
46+
47+
if (threadId == std::this_thread::get_id()) {
48+
// In case of a synchronous call, we should unlock mutexes and return.
49+
runtimeCaptured.unlock();
50+
jsBlockExecuted.unlock();
51+
return;
52+
}
53+
54+
runtimeCaptured.unlock();
55+
// `callback` is called somewhere here.
56+
callbackExecuted.lock();
57+
jsBlockExecuted.unlock();
58+
});
59+
60+
runtimeCaptured.lock();
61+
callback(*runtimePtr);
62+
callbackExecuted.unlock();
63+
jsBlockExecuted.lock();
64+
}
65+
66+
} // namespace facebook::react
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#include <ReactCommon/RuntimeExecutor.h>
9+
10+
#include <jsi/jsi.h>
11+
12+
namespace facebook::react {
13+
14+
/*
15+
* Executes a `callback` in a *synchronous* manner on the same thread using
16+
* given `RuntimeExecutor`.
17+
* Use this method when the caller needs to *be blocked* by executing the
18+
* `callback` and requires that the callback will be executed on the same
19+
* thread.
20+
*/
21+
void executeSynchronouslyOnSameThread_CAN_DEADLOCK(
22+
const RuntimeExecutor& runtimeExecutor,
23+
std::function<void(jsi::Runtime& runtime)>&& callback) noexcept;
24+
25+
template <typename DataT>
26+
DataT executeSynchronouslyOnSameThread_CAN_DEADLOCK(
27+
const RuntimeExecutor& runtimeExecutor,
28+
std::function<DataT(jsi::Runtime& runtime)>&& callback) noexcept {
29+
DataT data;
30+
31+
executeSynchronouslyOnSameThread_CAN_DEADLOCK(
32+
runtimeExecutor,
33+
[&](jsi::Runtime& runtime) { data = callback(runtime); });
34+
35+
return data;
36+
}
37+
} // namespace facebook::react
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#include <ReactCommon/RuntimeExecutor.h>
9+
10+
#include <jsi/jsi.h>
11+
12+
namespace facebook::react {
13+
14+
/*
15+
* Executes a `callback` in a *synchronous* manner on the same thread using
16+
* given `RuntimeExecutor`.
17+
* Use this method when the caller needs to *be blocked* by executing the
18+
* `callback` and requires that the callback will be executed on the same
19+
* thread.
20+
*/
21+
void executeSynchronouslyOnSameThread_CAN_DEADLOCK(
22+
const RuntimeExecutor& runtimeExecutor,
23+
std::function<void(jsi::Runtime& runtime)>&& callback) noexcept;
24+
25+
template <typename DataT>
26+
DataT executeSynchronouslyOnSameThread_CAN_DEADLOCK(
27+
const RuntimeExecutor& runtimeExecutor,
28+
std::function<DataT(jsi::Runtime& runtime)>&& callback) noexcept {
29+
DataT data;
30+
31+
executeSynchronouslyOnSameThread_CAN_DEADLOCK(
32+
runtimeExecutor,
33+
[&](jsi::Runtime& runtime) { data = callback(runtime); });
34+
35+
return data;
36+
}
37+
} // namespace facebook::react
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#import <ReactCommon/RuntimeExecutorUtils.h>
9+
#include <mutex>
10+
#include <thread>
11+
12+
namespace facebook::react {
13+
/**
14+
* Example order of events (when not a sync call in runtimeExecutor
15+
* callback):
16+
* - [UI thread] Lock all mutexes at start
17+
* - [UI thread] runtimeCaptured.lock before callback
18+
* - [JS thread] Set runtimePtr in runtimeExecutor callback
19+
* - [JS thread] runtimeCaptured.unlock in runtimeExecutor callback
20+
* - [UI thread] Call callback
21+
* - [JS thread] callbackExecuted.lock in runtimeExecutor callback
22+
* - [UI thread] callbackExecuted.unlock after callback
23+
* - [UI thread] jsBlockExecuted.lock after callback
24+
* - [JS thread] jsBlockExecuted.unlock in runtimeExecutor callback
25+
*/
26+
void executeSynchronouslyOnSameThread_CAN_DEADLOCK(
27+
const RuntimeExecutor &runtimeExecutor,
28+
std::function<void(jsi::Runtime &runtime)> &&callback) noexcept
29+
{
30+
// Note: We need the third mutex to get back to the main thread before
31+
// the lambda is finished (because all mutexes are allocated on the stack).
32+
33+
std::mutex runtimeCaptured;
34+
std::mutex callbackExecuted;
35+
std::mutex jsBlockExecuted;
36+
37+
runtimeCaptured.lock();
38+
callbackExecuted.lock();
39+
jsBlockExecuted.lock();
40+
41+
jsi::Runtime *runtimePtr;
42+
43+
auto threadId = std::this_thread::get_id();
44+
45+
runtimeExecutor([&](jsi::Runtime &runtime) {
46+
runtimePtr = &runtime;
47+
48+
if (threadId == std::this_thread::get_id()) {
49+
// In case of a synchronous call, we should unlock mutexes and return.
50+
runtimeCaptured.unlock();
51+
jsBlockExecuted.unlock();
52+
return;
53+
}
54+
55+
runtimeCaptured.unlock();
56+
// `callback` is called somewhere here.
57+
callbackExecuted.lock();
58+
jsBlockExecuted.unlock();
59+
});
60+
61+
runtimeCaptured.lock();
62+
callback(*runtimePtr);
63+
callbackExecuted.unlock();
64+
jsBlockExecuted.lock();
65+
}
66+
67+
} // namespace facebook::react

0 commit comments

Comments
 (0)