mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
RuntimeExecutor helpers that modify the way of the callback is being executed.
Summary: Here we implement a bunch of helper methods that allow customizing the behavior of a RuntimeExecutor "on-demand" on the caller side. We will use it in the next diff(s). Changelog: [Internal] Fabric-specific internal change. Reviewed By: PeteTheHeat Differential Revision: D20551411 fbshipit-source-id: 51d3cd02b69753110c0e1155347c6e52eb882c7d
This commit is contained in:
committed by
Facebook GitHub Bot
parent
b8664182da
commit
15ea60e3a8
@@ -7,6 +7,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
|
||||
#include <jsi/jsi.h>
|
||||
|
||||
namespace facebook {
|
||||
@@ -23,5 +26,84 @@ namespace react {
|
||||
using RuntimeExecutor =
|
||||
std::function<void(std::function<void(jsi::Runtime &runtime)> &&callback)>;
|
||||
|
||||
/*
|
||||
* The caller can expect that the callback will be executed sometime later on an
|
||||
* unspecified thread.
|
||||
* Use this method when the caller prefers to not be blocked by executing the
|
||||
* `callback`.
|
||||
* Note that this method does not provide any guarantees
|
||||
* about when the `callback` will be executed (before returning to the caller,
|
||||
* after that, or in parallel), the only thing that is guaranteed is that there
|
||||
* is no synchronization.
|
||||
*/
|
||||
inline static void executeAsynchronously(
|
||||
RuntimeExecutor const &runtimeExecutor,
|
||||
std::function<void(jsi::Runtime &runtime)> &&callback) noexcept {
|
||||
std::thread{[callback = std::move(callback), runtimeExecutor]() mutable {
|
||||
runtimeExecutor(std::move(callback));
|
||||
}};
|
||||
}
|
||||
|
||||
/*
|
||||
* Executes a `callback` in a *synchronous* manner using given
|
||||
* `RuntimeExecutor`.
|
||||
* Use this method when the caller needs to *be blocked* by executing the
|
||||
* callback but does not concerted about the particular thread on which the
|
||||
* `callback` will be executed.
|
||||
*/
|
||||
inline static void executeSynchronously_CAN_DEADLOCK(
|
||||
RuntimeExecutor const &runtimeExecutor,
|
||||
std::function<void(jsi::Runtime &runtime)> &&callback) noexcept {
|
||||
std::mutex mutex;
|
||||
mutex.lock();
|
||||
|
||||
runtimeExecutor(
|
||||
[callback = std::move(callback), &mutex](jsi::Runtime &runtime) {
|
||||
callback(runtime);
|
||||
mutex.unlock();
|
||||
});
|
||||
|
||||
mutex.lock();
|
||||
}
|
||||
|
||||
/*
|
||||
* Executes a `callback` in a *synchronous* manner on the same thread using
|
||||
* given `RuntimeExecutor`.
|
||||
* Use this method when the caller needs to *be blocked* by executing the
|
||||
* `callback` and requires that the callback will be executed on the same
|
||||
* thread.
|
||||
*/
|
||||
inline static void executeSynchronouslyOnSameThread_CAN_DEADLOCK(
|
||||
RuntimeExecutor const &runtimeExecutor,
|
||||
std::function<void(jsi::Runtime &runtime)> &&callback) noexcept {
|
||||
// Note: We need the third mutex to get back to the main thread before
|
||||
// the lambda is finished (because all mutexes are allocated on the stack).
|
||||
// We use `recursive_mutex` here to not deadlock in case if a
|
||||
// `RuntimeExecutor` executes the callback synchronously.
|
||||
|
||||
std::recursive_mutex mutex1;
|
||||
std::recursive_mutex mutex2;
|
||||
std::recursive_mutex mutex3;
|
||||
|
||||
mutex1.lock();
|
||||
mutex2.lock();
|
||||
mutex3.lock();
|
||||
|
||||
jsi::Runtime *runtimePtr;
|
||||
|
||||
runtimeExecutor([&](jsi::Runtime &runtime) {
|
||||
runtimePtr = &runtime;
|
||||
mutex1.unlock();
|
||||
// `callback` is called somewhere here.
|
||||
mutex2.lock();
|
||||
mutex3.unlock();
|
||||
});
|
||||
|
||||
mutex1.lock();
|
||||
callback(*runtimePtr);
|
||||
mutex2.unlock();
|
||||
mutex3.lock();
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
|
||||
Reference in New Issue
Block a user