Simplify RunLoop

Instead of transforming between return value and callback, pass
the wrapped callback on to the invoked function as the last argument.

This eliminates the need for multiple invokeWithArgument overloads
and permits invoked functions to be asynchronous.
This commit is contained in:
John Firebaugh
2015-06-11 19:03:19 -04:00
parent 3ab682e627
commit fc64e97bce
8 changed files with 149 additions and 216 deletions

View File

@@ -17,9 +17,9 @@ public:
EXPECT_EQ(val, 1);
}
int fn2() {
void fn2(std::function<void (int)> cb) {
EXPECT_EQ(tid, std::this_thread::get_id());
return 1;
cb(1);
}
void transferIn(std::unique_ptr<int> val) {
@@ -27,15 +27,15 @@ public:
EXPECT_EQ(*val, 1);
}
std::unique_ptr<int> transferOut() {
void transferOut(std::function<void (std::unique_ptr<int>)> cb) {
EXPECT_EQ(tid, std::this_thread::get_id());
return std::make_unique<int>(1);
cb(std::make_unique<int>(1));
}
std::unique_ptr<int> transferInOut(std::unique_ptr<int> val) {
void transferInOut(std::unique_ptr<int> val, std::function<void (std::unique_ptr<int>)> cb) {
EXPECT_EQ(tid, std::this_thread::get_id());
EXPECT_EQ(*val, 1);
return std::move(val);
cb(std::move(val));
}
void transferInShared(std::shared_ptr<int> val) {
@@ -43,21 +43,21 @@ public:
EXPECT_EQ(*val, 1);
}
std::shared_ptr<int> transferOutShared() {
void transferOutShared(std::function<void (std::shared_ptr<int>)> cb) {
EXPECT_EQ(tid, std::this_thread::get_id());
return std::make_shared<int>(1);
cb(std::make_shared<int>(1));
}
std::string transferString(const std::string& string) {
void transferString(const std::string& string, std::function<void (std::string)> cb) {
EXPECT_EQ(tid, std::this_thread::get_id());
EXPECT_EQ(string, "test");
return string;
cb(string);
}
bool checkContext() const {
return ThreadContext::currentlyOn(ThreadType::Worker)
void checkContext(std::function<void (bool)> cb) const {
cb(ThreadContext::currentlyOn(ThreadType::Worker)
&& ThreadContext::getName() == "Test"
&& ThreadContext::getPriority() == ThreadPriority::Low;
&& ThreadContext::getPriority() == ThreadPriority::Low);
}
const std::thread::id tid;
@@ -74,35 +74,35 @@ TEST(Thread, invoke) {
Thread<TestObject> thread({"Test", ThreadType::Map, ThreadPriority::Regular}, tid);
thread.invoke(&TestObject::fn1, 1);
requests.push_back(thread.invokeWithResult<int>(&TestObject::fn2, [&] (int result) {
requests.push_back(thread.invokeWithCallback(&TestObject::fn2, [&] (int result) {
EXPECT_EQ(tid, std::this_thread::get_id());
EXPECT_EQ(result, 1);
}));
thread.invoke(&TestObject::transferIn, std::make_unique<int>(1));
requests.push_back(thread.invokeWithResult<std::unique_ptr<int>>(&TestObject::transferOut, [&] (std::unique_ptr<int> result) {
requests.push_back(thread.invokeWithCallback(&TestObject::transferOut, [&] (std::unique_ptr<int> result) {
EXPECT_EQ(tid, std::this_thread::get_id());
EXPECT_EQ(*result, 1);
}));
requests.push_back(thread.invokeWithResult<std::unique_ptr<int>>(&TestObject::transferInOut, [&] (std::unique_ptr<int> result) {
requests.push_back(thread.invokeWithCallback(&TestObject::transferInOut, [&] (std::unique_ptr<int> result) {
EXPECT_EQ(tid, std::this_thread::get_id());
EXPECT_EQ(*result, 1);
}, std::make_unique<int>(1)));
thread.invoke(&TestObject::transferInShared, std::make_shared<int>(1));
requests.push_back(thread.invokeWithResult<std::shared_ptr<int>>(&TestObject::transferOutShared, [&] (std::shared_ptr<int> result) {
requests.push_back(thread.invokeWithCallback(&TestObject::transferOutShared, [&] (std::shared_ptr<int> result) {
EXPECT_EQ(tid, std::this_thread::get_id());
EXPECT_EQ(*result, 1);
}));
// Cancelled request
thread.invokeWithResult(&TestObject::fn1, [&] {
thread.invokeWithCallback(&TestObject::fn2, [&] (int) {
ADD_FAILURE();
}, 1);
});
std::string test("test");
requests.push_back(thread.invokeWithResult<std::string>(&TestObject::transferString, [&] (std::string result){
requests.push_back(thread.invokeWithCallback(&TestObject::transferString, [&] (std::string result){
EXPECT_EQ(tid, std::this_thread::get_id());
EXPECT_EQ(result, "test");
loop.stop();
@@ -128,7 +128,7 @@ TEST(Thread, context) {
loop.invoke([&] {
Thread<TestObject> thread({"Test", ThreadType::Worker, ThreadPriority::Low}, tid);
requests.push_back(thread.invokeWithResult<bool>(&TestObject::checkContext, [&] (bool inTestThreadContext) {
requests.push_back(thread.invokeWithCallback(&TestObject::checkContext, [&] (bool inTestThreadContext) {
EXPECT_EQ(inTestThreadContext, true);
loop.stop();
}));
@@ -139,8 +139,13 @@ TEST(Thread, context) {
class TestWorker {
public:
TestWorker(uv_loop_t*) {}
void send(std::function<void ()> fn) { fn(); }
TestWorker(uv_loop_t*) {
}
void send(std::function<void ()> fn, std::function<void ()> cb) {
fn();
cb();
}
};
TEST(Thread, ExecutesAfter) {
@@ -150,7 +155,7 @@ TEST(Thread, ExecutesAfter) {
bool didWork = false;
bool didAfter = false;
auto request = thread.invokeWithResult(&TestWorker::send, [&] {
auto request = thread.invokeWithCallback(&TestWorker::send, [&] {
didAfter = true;
loop.stop();
}, [&] {
@@ -170,7 +175,7 @@ TEST(Thread, WorkRequestDeletionWaitsForWorkToComplete) {
std::promise<void> started;
bool didWork = false;
auto request = thread.invokeWithResult(&TestWorker::send, [&] {}, [&] {
auto request = thread.invokeWithCallback(&TestWorker::send, [&] {}, [&] {
started.set_value();
usleep(10000);
didWork = true;
@@ -188,7 +193,7 @@ TEST(Thread, WorkRequestDeletionCancelsAfter) {
std::promise<void> started;
bool didAfter = false;
auto request = thread.invokeWithResult(&TestWorker::send, [&] {
auto request = thread.invokeWithCallback(&TestWorker::send, [&] {
didAfter = true;
}, [&] {
started.set_value();
@@ -206,12 +211,12 @@ TEST(Thread, WorkRequestDeletionCancelsImmediately) {
std::promise<void> started;
auto request1 = thread.invokeWithResult(&TestWorker::send, [&] {}, [&] {
auto request1 = thread.invokeWithCallback(&TestWorker::send, [&] {}, [&] {
usleep(10000);
started.set_value();
});
auto request2 = thread.invokeWithResult(&TestWorker::send, [&] {}, [&] {
auto request2 = thread.invokeWithCallback(&TestWorker::send, [&] {}, [&] {
ADD_FAILURE() << "Second work item should not be invoked";
});
request2.reset();