Add MessageQueueThread interface to react/

Summary:
Everything below the bridge interacts with just a MessageQueueThread. The implementation (JMessageQueueThread) is injected from react/jni.

public

Reviewed By: astreet

Differential Revision: D2905178

fb-gh-sync-id: 8b138e746d5a96dd70837bb2149cd4e188fcdacc
This commit is contained in:
Chris Hopman 2016-02-05 18:09:26 -08:00 committed by facebook-github-bot-2
parent 2997c8feed
commit f4b826d6a0
13 changed files with 67 additions and 29 deletions

View File

@ -61,6 +61,7 @@ react_library(
'JSCExecutor.h', 'JSCExecutor.h',
'JSCHelpers.h', 'JSCHelpers.h',
'JSCWebWorker.h', 'JSCWebWorker.h',
'MessageQueueThread.h',
'MethodCall.h', 'MethodCall.h',
'JSModulesUnbundle.h', 'JSModulesUnbundle.h',
'Value.h', 'Value.h',

View File

@ -12,7 +12,6 @@
#include <jni/fbjni/Exceptions.h> #include <jni/fbjni/Exceptions.h>
#include <sys/time.h> #include <sys/time.h>
#include "Value.h" #include "Value.h"
#include "jni/JMessageQueueThread.h"
#include "jni/OnLoad.h" #include "jni/OnLoad.h"
#include <react/JSCHelpers.h> #include <react/JSCHelpers.h>
#include "Platform.h" #include "Platform.h"
@ -91,7 +90,7 @@ std::unique_ptr<JSExecutor> JSCExecutorFactory::createJSExecutor(FlushImmediateC
JSCExecutor::JSCExecutor(FlushImmediateCallback cb, const std::string& cacheDir) : JSCExecutor::JSCExecutor(FlushImmediateCallback cb, const std::string& cacheDir) :
m_flushImmediateCallback(cb), m_deviceCacheDir(cacheDir) { m_flushImmediateCallback(cb), m_deviceCacheDir(cacheDir) {
m_context = JSGlobalContextCreateInGroup(nullptr, nullptr); m_context = JSGlobalContextCreateInGroup(nullptr, nullptr);
m_messageQueueThread = JMessageQueueThread::currentMessageQueueThread(); m_messageQueueThread = MessageQueues::getCurrentMessageQueueThread();
s_globalContextRefToJSCExecutor[m_context] = this; s_globalContextRefToJSCExecutor[m_context] = this;
installGlobalFunction(m_context, "nativeFlushQueueImmediate", nativeFlushQueueImmediate); installGlobalFunction(m_context, "nativeFlushQueueImmediate", nativeFlushQueueImmediate);
installGlobalFunction(m_context, "nativePerformanceNow", nativePerformanceNow); installGlobalFunction(m_context, "nativePerformanceNow", nativePerformanceNow);
@ -255,7 +254,7 @@ JSGlobalContextRef JSCExecutor::getContext() {
return m_context; return m_context;
} }
std::shared_ptr<JMessageQueueThread> JSCExecutor::getMessageQueueThread() { std::shared_ptr<MessageQueueThread> JSCExecutor::getMessageQueueThread() {
return m_messageQueueThread; return m_messageQueueThread;
} }

View File

@ -13,7 +13,7 @@
namespace facebook { namespace facebook {
namespace react { namespace react {
class JMessageQueueThread; class MessageQueueThread;
class JSCExecutorFactory : public JSExecutorFactory { class JSCExecutorFactory : public JSExecutorFactory {
public: public:
@ -59,16 +59,16 @@ public:
void installNativeHook(const char *name, JSObjectCallAsFunctionCallback callback); void installNativeHook(const char *name, JSObjectCallAsFunctionCallback callback);
virtual void onMessageReceived(int workerId, const std::string& message) override; virtual void onMessageReceived(int workerId, const std::string& message) override;
virtual JSGlobalContextRef getContext() override; virtual JSGlobalContextRef getContext() override;
virtual std::shared_ptr<JMessageQueueThread> getMessageQueueThread() override; virtual std::shared_ptr<MessageQueueThread> getMessageQueueThread() override;
private: private:
JSGlobalContextRef m_context; JSGlobalContextRef m_context;
FlushImmediateCallback m_flushImmediateCallback; FlushImmediateCallback m_flushImmediateCallback;
std::unordered_map<int, JSCWebWorker> m_webWorkers; std::unordered_map<int, JSCWebWorker> m_webWorkers;
std::unordered_map<int, Object> m_webWorkerJSObjs; std::unordered_map<int, Object> m_webWorkerJSObjs;
std::shared_ptr<JMessageQueueThread> m_messageQueueThread;
JSModulesUnbundle m_unbundle; JSModulesUnbundle m_unbundle;
bool m_isUnbundleInitialized = false; bool m_isUnbundleInitialized = false;
std::shared_ptr<MessageQueueThread> m_messageQueueThread;
std::string m_deviceCacheDir; std::string m_deviceCacheDir;
int addWebWorker(const std::string& script, JSValueRef workerRef); int addWebWorker(const std::string& script, JSValueRef workerRef);

View File

@ -13,9 +13,9 @@
#include <jni/LocalReference.h> #include <jni/LocalReference.h>
#include "JSCHelpers.h" #include "JSCHelpers.h"
#include "jni/JMessageQueueThread.h"
#include "jni/JSLoader.h" #include "jni/JSLoader.h"
#include "jni/WebWorkers.h" #include "jni/WebWorkers.h"
#include "MessageQueueThread.h"
#include "Platform.h" #include "Platform.h"
#include "Value.h" #include "Value.h"

View File

@ -14,7 +14,7 @@
namespace facebook { namespace facebook {
namespace react { namespace react {
class JMessageQueueThread; class MessageQueueThread;
/** /**
* A class that can own the lifecycle, receive messages from, and dispatch messages * A class that can own the lifecycle, receive messages from, and dispatch messages
@ -32,7 +32,7 @@ public:
* Should return the owner's MessageQueueThread. Calls to onMessageReceived will be enqueued * Should return the owner's MessageQueueThread. Calls to onMessageReceived will be enqueued
* on this thread. * on this thread.
*/ */
virtual std::shared_ptr<JMessageQueueThread> getMessageQueueThread() = 0; virtual std::shared_ptr<MessageQueueThread> getMessageQueueThread() = 0;
}; };
/** /**
@ -77,8 +77,8 @@ private:
std::atomic_bool isTerminated_ = ATOMIC_VAR_INIT(false); std::atomic_bool isTerminated_ = ATOMIC_VAR_INIT(false);
std::string scriptName_; std::string scriptName_;
JSCWebWorkerOwner *owner_ = nullptr; JSCWebWorkerOwner *owner_ = nullptr;
std::shared_ptr<JMessageQueueThread> ownerMessageQueueThread_; std::shared_ptr<MessageQueueThread> ownerMessageQueueThread_;
std::unique_ptr<JMessageQueueThread> workerMessageQueueThread_; std::unique_ptr<MessageQueueThread> workerMessageQueueThread_;
JSGlobalContextRef context_ = nullptr; JSGlobalContextRef context_ = nullptr;
static JSValueRef nativePostMessage( static JSValueRef nativePostMessage(

View File

@ -0,0 +1,19 @@
// Copyright 2004-present Facebook. All Rights Reserved.
#pragma once
#include <functional>
namespace facebook {
namespace react {
class MessageQueueThread {
public:
virtual ~MessageQueueThread() {}
virtual void runOnQueue(std::function<void()>&&) = 0;
virtual bool isOnThread() = 0;
// quitSynchronous() should synchronously ensure that no further tasks will run on the queue.
virtual void quitSynchronous() = 0;
};
}}

View File

@ -9,6 +9,10 @@ namespace ReactMarker {
LogMarker logMarker; LogMarker logMarker;
}; };
namespace MessageQueues {
GetCurrentMessageQueueThread getCurrentMessageQueueThread;
};
namespace WebWorkerUtil { namespace WebWorkerUtil {
LoadScriptFromAssets loadScriptFromAssets; LoadScriptFromAssets loadScriptFromAssets;
}; };

View File

@ -6,6 +6,8 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include "MessageQueueThread.h"
#include <JavaScriptCore/JSContextRef.h> #include <JavaScriptCore/JSContextRef.h>
namespace facebook { namespace facebook {
@ -16,6 +18,11 @@ using LogMarker = std::function<void(const std::string&)>;
extern LogMarker logMarker; extern LogMarker logMarker;
}; };
namespace MessageQueues {
using GetCurrentMessageQueueThread = std::function<std::unique_ptr<MessageQueueThread>()>;
extern GetCurrentMessageQueueThread getCurrentMessageQueueThread;
};
namespace WebWorkerUtil { namespace WebWorkerUtil {
using LoadScriptFromAssets = std::function<std::string(const std::string& assetName)>; using LoadScriptFromAssets = std::function<std::string(const std::string& assetName)>;
extern LoadScriptFromAssets loadScriptFromAssets; extern LoadScriptFromAssets loadScriptFromAssets;

View File

@ -39,12 +39,12 @@ jni_library(
headers = [ headers = [
'JSLoader.h', 'JSLoader.h',
'ProxyExecutor.h', 'ProxyExecutor.h',
'JMessageQueueThread.h',
'JNativeRunnable.h',
'JSCPerfLogging.h', 'JSCPerfLogging.h',
'JSLogging.h', 'JSLogging.h',
], ],
exported_headers = [ exported_headers = [
'JMessageQueueThread.h',
'JNativeRunnable.h',
'NativeArray.h', 'NativeArray.h',
'ReadableNativeArray.h', 'ReadableNativeArray.h',
'WebWorkers.h', 'WebWorkers.h',

View File

@ -11,24 +11,24 @@
namespace facebook { namespace facebook {
namespace react { namespace react {
JMessageQueueThread::JMessageQueueThread(alias_ref<MessageQueueThread::javaobject> jobj) : JMessageQueueThread::JMessageQueueThread(alias_ref<JavaMessageQueueThread::javaobject> jobj) :
m_jobj(make_global(jobj)) { m_jobj(make_global(jobj)) {
} }
void JMessageQueueThread::runOnQueue(std::function<void()>&& runnable) { void JMessageQueueThread::runOnQueue(std::function<void()>&& runnable) {
static auto method = MessageQueueThread::javaClassStatic()-> static auto method = JavaMessageQueueThread::javaClassStatic()->
getMethod<void(Runnable::javaobject)>("runOnQueue"); getMethod<void(Runnable::javaobject)>("runOnQueue");
method(m_jobj, JNativeRunnable::newObjectCxxArgs(runnable).get()); method(m_jobj, JNativeRunnable::newObjectCxxArgs(runnable).get());
} }
bool JMessageQueueThread::isOnThread() { bool JMessageQueueThread::isOnThread() {
static auto method = MessageQueueThread::javaClassStatic()-> static auto method = JavaMessageQueueThread::javaClassStatic()->
getMethod<jboolean()>("isOnThread"); getMethod<jboolean()>("isOnThread");
return method(m_jobj); return method(m_jobj);
} }
void JMessageQueueThread::quitSynchronous() { void JMessageQueueThread::quitSynchronous() {
static auto method = MessageQueueThread::javaClassStatic()-> static auto method = JavaMessageQueueThread::javaClassStatic()->
getMethod<void()>("quitSynchronous"); getMethod<void()>("quitSynchronous");
method(m_jobj); method(m_jobj);
} }
@ -36,7 +36,7 @@ void JMessageQueueThread::quitSynchronous() {
/* static */ /* static */
std::unique_ptr<JMessageQueueThread> JMessageQueueThread::currentMessageQueueThread() { std::unique_ptr<JMessageQueueThread> JMessageQueueThread::currentMessageQueueThread() {
static auto method = MessageQueueThreadRegistry::javaClassStatic()-> static auto method = MessageQueueThreadRegistry::javaClassStatic()->
getStaticMethod<MessageQueueThread::javaobject()>("myMessageQueueThread"); getStaticMethod<JavaMessageQueueThread::javaobject()>("myMessageQueueThread");
return folly::make_unique<JMessageQueueThread>(method(MessageQueueThreadRegistry::javaClassStatic())); return folly::make_unique<JMessageQueueThread>(method(MessageQueueThreadRegistry::javaClassStatic()));
} }

View File

@ -4,6 +4,8 @@
#include <functional> #include <functional>
#include <react/MessageQueueThread.h>
#include <jni/fbjni.h> #include <jni/fbjni.h>
using namespace facebook::jni; using namespace facebook::jni;
@ -11,32 +13,32 @@ using namespace facebook::jni;
namespace facebook { namespace facebook {
namespace react { namespace react {
class MessageQueueThread : public jni::JavaClass<MessageQueueThread> { class JavaMessageQueueThread : public jni::JavaClass<JavaMessageQueueThread> {
public: public:
static constexpr auto kJavaDescriptor = "Lcom/facebook/react/bridge/queue/MessageQueueThread;"; static constexpr auto kJavaDescriptor = "Lcom/facebook/react/bridge/queue/MessageQueueThread;";
}; };
class JMessageQueueThread { class JMessageQueueThread : public MessageQueueThread {
public: public:
JMessageQueueThread(alias_ref<MessageQueueThread::javaobject> jobj); JMessageQueueThread(alias_ref<JavaMessageQueueThread::javaobject> jobj);
/** /**
* Enqueues the given function to run on this MessageQueueThread. * Enqueues the given function to run on this MessageQueueThread.
*/ */
void runOnQueue(std::function<void()>&& runnable); void runOnQueue(std::function<void()>&& runnable) override;
/** /**
* Returns whether the currently executing thread is this MessageQueueThread. * Returns whether the currently executing thread is this MessageQueueThread.
*/ */
bool isOnThread(); bool isOnThread() override;
/** /**
* Synchronously quits the current MessageQueueThread. Can be called from any thread, but will * Synchronously quits the current MessageQueueThread. Can be called from any thread, but will
* block if not called on this MessageQueueThread. * block if not called on this MessageQueueThread.
*/ */
void quitSynchronous(); void quitSynchronous() override;
MessageQueueThread::javaobject jobj() { JavaMessageQueueThread::javaobject jobj() {
return m_jobj.get(); return m_jobj.get();
} }
@ -45,7 +47,7 @@ public:
*/ */
static std::unique_ptr<JMessageQueueThread> currentMessageQueueThread(); static std::unique_ptr<JMessageQueueThread> currentMessageQueueThread();
private: private:
global_ref<MessageQueueThread::javaobject> m_jobj; global_ref<JavaMessageQueueThread::javaobject> m_jobj;
}; };
class MessageQueueThreadRegistry : public jni::JavaClass<MessageQueueThreadRegistry> { class MessageQueueThreadRegistry : public jni::JavaClass<MessageQueueThreadRegistry> {

View File

@ -21,6 +21,7 @@
#include "ReadableNativeArray.h" #include "ReadableNativeArray.h"
#include "ProxyExecutor.h" #include "ProxyExecutor.h"
#include "OnLoad.h" #include "OnLoad.h"
#include "JMessageQueueThread.h"
#include "JSLogging.h" #include "JSLogging.h"
#include "JSCPerfLogging.h" #include "JSCPerfLogging.h"
#include <algorithm> #include <algorithm>
@ -842,6 +843,11 @@ extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
[] (const std::string& assetName) { [] (const std::string& assetName) {
return loadScriptFromAssets(assetName); return loadScriptFromAssets(assetName);
}; };
MessageQueues::getCurrentMessageQueueThread =
[] {
return std::unique_ptr<MessageQueueThread>(
JMessageQueueThread::currentMessageQueueThread().release());
};
PerfLogging::installNativeHooks = addNativePerfLoggingHooks; PerfLogging::installNativeHooks = addNativePerfLoggingHooks;
JSLogging::nativeHook = nativeLoggingHook; JSLogging::nativeHook = nativeLoggingHook;

View File

@ -18,10 +18,10 @@ class WebWorkers : public JavaClass<WebWorkers> {
public: public:
static constexpr auto kJavaDescriptor = "Lcom/facebook/react/bridge/webworkers/WebWorkers;"; static constexpr auto kJavaDescriptor = "Lcom/facebook/react/bridge/webworkers/WebWorkers;";
static std::unique_ptr<JMessageQueueThread> createWebWorkerThread(int id, JMessageQueueThread *ownerMessageQueueThread) { static std::unique_ptr<JMessageQueueThread> createWebWorkerThread(int id, MessageQueueThread *ownerMessageQueueThread) {
static auto method = WebWorkers::javaClassStatic()-> static auto method = WebWorkers::javaClassStatic()->
getStaticMethod<MessageQueueThread::javaobject(jint, MessageQueueThread::javaobject)>("createWebWorkerThread"); getStaticMethod<JavaMessageQueueThread::javaobject(jint, JavaMessageQueueThread::javaobject)>("createWebWorkerThread");
auto res = method(WebWorkers::javaClassStatic(), id, ownerMessageQueueThread->jobj()); auto res = method(WebWorkers::javaClassStatic(), id, static_cast<JMessageQueueThread*>(ownerMessageQueueThread)->jobj());
return folly::make_unique<JMessageQueueThread>(res); return folly::make_unique<JMessageQueueThread>(res);
} }
}; };