Tweak CxxMessageQueue to work with unique_ptr
Differential Revision: D4560164 fbshipit-source-id: 8975157f5a14d5849365a9e35922a02ac6dc185b
This commit is contained in:
parent
406a4c04d3
commit
6bce498bbc
|
@ -56,6 +56,7 @@ if THIS_IS_FBANDROID:
|
||||||
# `initOnJSVMThread` to be called before the platform-specific hooks
|
# `initOnJSVMThread` to be called before the platform-specific hooks
|
||||||
# have been properly initialised. Bad Times(TM).
|
# have been properly initialised. Bad Times(TM).
|
||||||
# -- @ashokmenon (2017/01/03)
|
# -- @ashokmenon (2017/01/03)
|
||||||
|
'//java/com/facebook/java2js:jni',
|
||||||
react_native_target('jni/xreact/jni:jni'),
|
react_native_target('jni/xreact/jni:jni'),
|
||||||
react_native_xplat_target('cxxreact/...'),
|
react_native_xplat_target('cxxreact/...'),
|
||||||
],
|
],
|
||||||
|
@ -158,7 +159,6 @@ react_library(
|
||||||
compiler_flags = [
|
compiler_flags = [
|
||||||
"-Wall",
|
"-Wall",
|
||||||
"-fexceptions",
|
"-fexceptions",
|
||||||
"-fvisibility=hidden",
|
|
||||||
"-frtti",
|
"-frtti",
|
||||||
"-std=c++1y",
|
"-std=c++1y",
|
||||||
] + REACT_LIBRARY_EXTRA_COMPILER_FLAGS,
|
] + REACT_LIBRARY_EXTRA_COMPILER_FLAGS,
|
||||||
|
|
|
@ -192,6 +192,7 @@ class CxxMessageQueue::QueueRunner {
|
||||||
}
|
}
|
||||||
|
|
||||||
void bindToThisThread() {
|
void bindToThisThread() {
|
||||||
|
// TODO: handle nested runloops (either allow them or throw an exception).
|
||||||
if (tid_ != std::thread::id{}) {
|
if (tid_ != std::thread::id{}) {
|
||||||
throw std::runtime_error("Message queue already bound to thread.");
|
throw std::runtime_error("Message queue already bound to thread.");
|
||||||
}
|
}
|
||||||
|
@ -290,9 +291,16 @@ MQRegistry& getMQRegistry() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::weak_ptr<CxxMessageQueue> CxxMessageQueue::current() {
|
std::shared_ptr<CxxMessageQueue> CxxMessageQueue::current() {
|
||||||
auto tid = std::this_thread::get_id();
|
auto tid = std::this_thread::get_id();
|
||||||
return getMQRegistry().find(tid);
|
return getMQRegistry().find(tid).lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::function<void()> CxxMessageQueue::getUnregisteredRunLoop() {
|
||||||
|
return [capture=qr_] {
|
||||||
|
capture->bindToThisThread();
|
||||||
|
capture->run();
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::function<void()> CxxMessageQueue::getRunLoop(std::shared_ptr<CxxMessageQueue> mq) {
|
std::function<void()> CxxMessageQueue::getRunLoop(std::shared_ptr<CxxMessageQueue> mq) {
|
||||||
|
@ -300,7 +308,6 @@ std::function<void()> CxxMessageQueue::getRunLoop(std::shared_ptr<CxxMessageQueu
|
||||||
capture->bindToThisThread();
|
capture->bindToThisThread();
|
||||||
auto tid = std::this_thread::get_id();
|
auto tid = std::this_thread::get_id();
|
||||||
|
|
||||||
// TODO: handle nested runloops (either allow them or throw an exception).
|
|
||||||
getMQRegistry().registerQueue(tid, weakMq);
|
getMQRegistry().registerQueue(tid, weakMq);
|
||||||
capture->run();
|
capture->run();
|
||||||
getMQRegistry().unregister(tid);
|
getMQRegistry().unregister(tid);
|
||||||
|
|
|
@ -62,6 +62,9 @@ class CxxMessageQueue : public MessageQueueThread {
|
||||||
|
|
||||||
bool isOnQueue();
|
bool isOnQueue();
|
||||||
|
|
||||||
|
// If this getRunLoop is used, current() will not work.
|
||||||
|
std::function<void()> getUnregisteredRunLoop();
|
||||||
|
|
||||||
// This returns a function that will actually run the runloop.
|
// This returns a function that will actually run the runloop.
|
||||||
// This runloop will return some time after quitSynchronous (or after this is destroyed).
|
// This runloop will return some time after quitSynchronous (or after this is destroyed).
|
||||||
//
|
//
|
||||||
|
@ -71,7 +74,7 @@ class CxxMessageQueue : public MessageQueueThread {
|
||||||
// Only one thread should run the runloop.
|
// Only one thread should run the runloop.
|
||||||
static std::function<void()> getRunLoop(std::shared_ptr<CxxMessageQueue> mq);
|
static std::function<void()> getRunLoop(std::shared_ptr<CxxMessageQueue> mq);
|
||||||
|
|
||||||
static std::weak_ptr<CxxMessageQueue> current();
|
static std::shared_ptr<CxxMessageQueue> current();
|
||||||
private:
|
private:
|
||||||
class QueueRunner;
|
class QueueRunner;
|
||||||
std::shared_ptr<QueueRunner> qr_;
|
std::shared_ptr<QueueRunner> qr_;
|
||||||
|
|
|
@ -20,6 +20,7 @@ if THIS_IS_FBANDROID:
|
||||||
srcs = TEST_SRCS,
|
srcs = TEST_SRCS,
|
||||||
compiler_flags = [
|
compiler_flags = [
|
||||||
'-fexceptions',
|
'-fexceptions',
|
||||||
|
'-std=c++1y',
|
||||||
],
|
],
|
||||||
deps = [
|
deps = [
|
||||||
'//native/third-party/android-ndk:android',
|
'//native/third-party/android-ndk:android',
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||||
|
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
#include <cxxreact/CxxMessageQueue.h>
|
#include <cxxreact/CxxMessageQueue.h>
|
||||||
|
@ -29,6 +31,17 @@ std::shared_ptr<CxxMessageQueue> createAndStartQueue(EventFlag& finishedFlag) {
|
||||||
return q;
|
return q;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<CxxMessageQueue> createAndStartUnregisteredQueue(
|
||||||
|
EventFlag& finishedFlag) {
|
||||||
|
auto q = std::make_unique<CxxMessageQueue>();
|
||||||
|
std::thread t([loop=q->getUnregisteredRunLoop(), &finishedFlag] {
|
||||||
|
loop();
|
||||||
|
finishedFlag.set();
|
||||||
|
});
|
||||||
|
t.detach();
|
||||||
|
return q;
|
||||||
|
}
|
||||||
|
|
||||||
// This is just used to start up a queue for a test and make sure that it is
|
// This is just used to start up a queue for a test and make sure that it is
|
||||||
// actually shut down after the test.
|
// actually shut down after the test.
|
||||||
struct QueueWithThread {
|
struct QueueWithThread {
|
||||||
|
@ -39,9 +52,7 @@ struct QueueWithThread {
|
||||||
~QueueWithThread() {
|
~QueueWithThread() {
|
||||||
queue->quitSynchronous();
|
queue->quitSynchronous();
|
||||||
queue.reset();
|
queue.reset();
|
||||||
if (!done.wait_until(now() + milliseconds(300))) {
|
EXPECT_TRUE(done.wait_until(now() + milliseconds(300))) << "Queue did not exit";
|
||||||
ADD_FAILURE() << "Queue did not exit";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EventFlag done;
|
EventFlag done;
|
||||||
|
@ -53,9 +64,8 @@ TEST(CxxMessageQueue, TestQuit) {
|
||||||
EventFlag done;
|
EventFlag done;
|
||||||
auto q = createAndStartQueue(done);
|
auto q = createAndStartQueue(done);
|
||||||
q->quitSynchronous();
|
q->quitSynchronous();
|
||||||
if (!done.wait_until(now() + milliseconds(300))) {
|
EXPECT_TRUE(done.wait_until(now() + milliseconds(300)))
|
||||||
FAIL() << "Queue did not exit runloop after quitSynchronous";
|
<< "Queue did not exit runloop after quitSynchronous";
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CxxMessageQueue, TestPostTask) {
|
TEST(CxxMessageQueue, TestPostTask) {
|
||||||
|
@ -69,6 +79,34 @@ TEST(CxxMessageQueue, TestPostTask) {
|
||||||
flag.wait();
|
flag.wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(CxxMessageQueue, TestPostUnregistered) {
|
||||||
|
EventFlag qdone;
|
||||||
|
auto q = createAndStartUnregisteredQueue(qdone);
|
||||||
|
|
||||||
|
EventFlag tflag;
|
||||||
|
q->runOnQueue([&] {
|
||||||
|
tflag.set();
|
||||||
|
});
|
||||||
|
tflag.wait();
|
||||||
|
|
||||||
|
q->quitSynchronous();
|
||||||
|
q.reset();
|
||||||
|
EXPECT_TRUE(qdone.wait_until(now() + milliseconds(300))) << "Queue did not exit";
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CxxMessageQueue, TestPostCurrent) {
|
||||||
|
QueueWithThread qt;
|
||||||
|
auto q = qt.queue;
|
||||||
|
|
||||||
|
EventFlag flag;
|
||||||
|
q->runOnQueue([&] {
|
||||||
|
CxxMessageQueue::current()->runOnQueue([&] {
|
||||||
|
flag.set();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
flag.wait();
|
||||||
|
}
|
||||||
|
|
||||||
TEST(CxxMessageQueue, TestPostTaskMultiple) {
|
TEST(CxxMessageQueue, TestPostTaskMultiple) {
|
||||||
QueueWithThread qt;
|
QueueWithThread qt;
|
||||||
auto q = qt.queue;
|
auto q = qt.queue;
|
||||||
|
|
|
@ -14,7 +14,7 @@ namespace {
|
||||||
int tempFileFromString(std::string contents)
|
int tempFileFromString(std::string contents)
|
||||||
{
|
{
|
||||||
std::string tmp {getenv("TMPDIR")};
|
std::string tmp {getenv("TMPDIR")};
|
||||||
tmp += "/temp.XXXXX";
|
tmp += "/temp.XXXXXX";
|
||||||
|
|
||||||
std::vector<char> tmpBuf {tmp.begin(), tmp.end()};
|
std::vector<char> tmpBuf {tmp.begin(), tmp.end()};
|
||||||
tmpBuf.push_back('\0');
|
tmpBuf.push_back('\0');
|
||||||
|
|
Loading…
Reference in New Issue