[core] Add Scheduler::scheduleAndReplyValue() API

This commit is contained in:
Mikhail Pozdnyakov
2019-10-28 17:12:58 +02:00
parent d8b1b2bacf
commit 31421f8448
3 changed files with 48 additions and 2 deletions

View File

@@ -50,6 +50,18 @@ public:
// first invoked, the call is ignored.
std::function<void()> bindOnce(std::function<void()>);
// Enqueues the given |task| for execution into this scheduler's task queue and
// then enqueues the |reply| with the captured task result to the current
// task queue.
//
// The |TaskFn| return type must be compatible with the |ReplyFn| argument type.
// Note: the task result is copied and passed by value.
template <typename TaskFn, typename ReplyFn>
void scheduleAndReplyValue(const TaskFn& task, const ReplyFn& reply) {
assert(GetCurrent());
scheduleAndReplyValue(task, reply, GetCurrent()->makeWeakPtr());
}
// Set/Get the current Scheduler for this thread
static Scheduler* GetCurrent();
static void SetCurrent(Scheduler*);
@@ -58,6 +70,21 @@ public:
// will lazily initialize a shared worker pool when ran
// from the first time.
static std::shared_ptr<Scheduler> GetBackground();
protected:
template <typename TaskFn, typename ReplyFn>
void scheduleAndReplyValue(const TaskFn& task,
const ReplyFn& reply,
mapbox::base::WeakPtr<Scheduler> replyScheduler) {
auto scheduled = [replyScheduler, task, reply] {
auto lock = replyScheduler.lock();
if (!replyScheduler) return;
auto scheduledReply = [reply, result = task()] { reply(result); };
replyScheduler->schedule(std::move(scheduledReply));
};
schedule(std::move(scheduled));
}
};
} // namespace mbgl

View File

@@ -60,11 +60,11 @@ private:
static_assert(N > 0, "Thread count must be more than zero.");
};
using SequencedScheduler = ThreadedScheduler<1>;
class SequencedScheduler : public ThreadedScheduler<1> {};
template <std::size_t extra>
using ParallelScheduler = ThreadedScheduler<1 + extra>;
using ThreadPool = ParallelScheduler<3>;
class ThreadPool : public ParallelScheduler<3> {};
} // namespace mbgl

View File

@@ -151,3 +151,22 @@ TEST(AsyncTask, ThreadSafety) {
// a valid result, although very unlikely (I hope).
EXPECT_GT(count, 0u);
}
TEST(AsyncTask, scheduleAndReplyValue) {
RunLoop loop;
std::thread::id caller_id = std::this_thread::get_id();
auto runInBackground = [caller_id]() -> int {
EXPECT_NE(caller_id, std::this_thread::get_id());
return 42;
};
auto onResult = [caller_id, &loop](int res) {
EXPECT_EQ(caller_id, std::this_thread::get_id());
EXPECT_EQ(42, res);
loop.stop();
};
auto sheduler = Scheduler::GetBackground();
sheduler->scheduleAndReplyValue(runInBackground, onResult);
loop.run();
}