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',
'JSCHelpers.h',
'JSCWebWorker.h',
'MessageQueueThread.h',
'MethodCall.h',
'JSModulesUnbundle.h',
'Value.h',

View File

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

View File

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

View File

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

View File

@ -14,7 +14,7 @@
namespace facebook {
namespace react {
class JMessageQueueThread;
class MessageQueueThread;
/**
* 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
* 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::string scriptName_;
JSCWebWorkerOwner *owner_ = nullptr;
std::shared_ptr<JMessageQueueThread> ownerMessageQueueThread_;
std::unique_ptr<JMessageQueueThread> workerMessageQueueThread_;
std::shared_ptr<MessageQueueThread> ownerMessageQueueThread_;
std::unique_ptr<MessageQueueThread> workerMessageQueueThread_;
JSGlobalContextRef context_ = nullptr;
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;
};
namespace MessageQueues {
GetCurrentMessageQueueThread getCurrentMessageQueueThread;
};
namespace WebWorkerUtil {
LoadScriptFromAssets loadScriptFromAssets;
};

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -18,10 +18,10 @@ class WebWorkers : public JavaClass<WebWorkers> {
public:
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()->
getStaticMethod<MessageQueueThread::javaobject(jint, MessageQueueThread::javaobject)>("createWebWorkerThread");
auto res = method(WebWorkers::javaClassStatic(), id, ownerMessageQueueThread->jobj());
getStaticMethod<JavaMessageQueueThread::javaobject(jint, JavaMessageQueueThread::javaobject)>("createWebWorkerThread");
auto res = method(WebWorkers::javaClassStatic(), id, static_cast<JMessageQueueThread*>(ownerMessageQueueThread)->jobj());
return folly::make_unique<JMessageQueueThread>(res);
}
};