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
|
||||
# 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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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_;
|
||||
|
|
|
@ -20,6 +20,7 @@ if THIS_IS_FBANDROID:
|
|||
srcs = TEST_SRCS,
|
||||
compiler_flags = [
|
||||
'-fexceptions',
|
||||
'-std=c++1y',
|
||||
],
|
||||
deps = [
|
||||
'//native/third-party/android-ndk:android',
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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');
|
||||
|
|
Loading…
Reference in New Issue