Tweak CxxMessageQueue to work with unique_ptr

Differential Revision: D4560164

fbshipit-source-id: 8975157f5a14d5849365a9e35922a02ac6dc185b
This commit is contained in:
Marc Horowitz 2017-02-28 14:14:51 -08:00 committed by Facebook Github Bot
parent 406a4c04d3
commit 6bce498bbc
6 changed files with 61 additions and 12 deletions

View File

@ -56,6 +56,7 @@ if THIS_IS_FBANDROID:
# `initOnJSVMThread` to be called before the platform-specific hooks
# have been properly initialised. Bad Times(TM).
# -- @ashokmenon (2017/01/03)
'//java/com/facebook/java2js:jni',
react_native_target('jni/xreact/jni:jni'),
react_native_xplat_target('cxxreact/...'),
],
@ -158,7 +159,6 @@ react_library(
compiler_flags = [
"-Wall",
"-fexceptions",
"-fvisibility=hidden",
"-frtti",
"-std=c++1y",
] + REACT_LIBRARY_EXTRA_COMPILER_FLAGS,

View File

@ -192,6 +192,7 @@ class CxxMessageQueue::QueueRunner {
}
void bindToThisThread() {
// TODO: handle nested runloops (either allow them or throw an exception).
if (tid_ != std::thread::id{}) {
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();
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) {
@ -300,7 +308,6 @@ std::function<void()> CxxMessageQueue::getRunLoop(std::shared_ptr<CxxMessageQueu
capture->bindToThisThread();
auto tid = std::this_thread::get_id();
// TODO: handle nested runloops (either allow them or throw an exception).
getMQRegistry().registerQueue(tid, weakMq);
capture->run();
getMQRegistry().unregister(tid);

View File

@ -62,6 +62,9 @@ class CxxMessageQueue : public MessageQueueThread {
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 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.
static std::function<void()> getRunLoop(std::shared_ptr<CxxMessageQueue> mq);
static std::weak_ptr<CxxMessageQueue> current();
static std::shared_ptr<CxxMessageQueue> current();
private:
class QueueRunner;
std::shared_ptr<QueueRunner> qr_;

View File

@ -20,6 +20,7 @@ if THIS_IS_FBANDROID:
srcs = TEST_SRCS,
compiler_flags = [
'-fexceptions',
'-std=c++1y',
],
deps = [
'//native/third-party/android-ndk:android',

View File

@ -1,3 +1,5 @@
// Copyright 2004-present Facebook. All Rights Reserved.
#include <gtest/gtest.h>
#include <cxxreact/CxxMessageQueue.h>
@ -29,6 +31,17 @@ std::shared_ptr<CxxMessageQueue> createAndStartQueue(EventFlag& finishedFlag) {
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
// actually shut down after the test.
struct QueueWithThread {
@ -39,9 +52,7 @@ struct QueueWithThread {
~QueueWithThread() {
queue->quitSynchronous();
queue.reset();
if (!done.wait_until(now() + milliseconds(300))) {
ADD_FAILURE() << "Queue did not exit";
}
EXPECT_TRUE(done.wait_until(now() + milliseconds(300))) << "Queue did not exit";
}
EventFlag done;
@ -53,9 +64,8 @@ TEST(CxxMessageQueue, TestQuit) {
EventFlag done;
auto q = createAndStartQueue(done);
q->quitSynchronous();
if (!done.wait_until(now() + milliseconds(300))) {
FAIL() << "Queue did not exit runloop after quitSynchronous";
}
EXPECT_TRUE(done.wait_until(now() + milliseconds(300)))
<< "Queue did not exit runloop after quitSynchronous";
}
TEST(CxxMessageQueue, TestPostTask) {
@ -69,6 +79,34 @@ TEST(CxxMessageQueue, TestPostTask) {
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) {
QueueWithThread qt;
auto q = qt.queue;

View File

@ -14,7 +14,7 @@ namespace {
int tempFileFromString(std::string contents)
{
std::string tmp {getenv("TMPDIR")};
tmp += "/temp.XXXXX";
tmp += "/temp.XXXXXX";
std::vector<char> tmpBuf {tmp.begin(), tmp.end()};
tmpBuf.push_back('\0');