summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMikhail Pozdnyakov <mikhail.pozdnyakov@mapbox.com>2019-10-28 17:12:58 +0200
committerMikhail Pozdnyakov <mikhail.pozdnyakov@mapbox.com>2019-11-05 11:45:38 +0200
commit31421f8448d0192d04b95e31a0aecde2675b5988 (patch)
tree6fa71a14f10728e49997d8581e00929bce59c414
parentd8b1b2bacf0dd9812d62077a825067441037791b (diff)
downloadqtlocation-mapboxgl-31421f8448d0192d04b95e31a0aecde2675b5988.tar.gz
[core] Add Scheduler::scheduleAndReplyValue() API
-rw-r--r--include/mbgl/actor/scheduler.hpp27
-rw-r--r--src/mbgl/util/thread_pool.hpp4
-rw-r--r--test/util/async_task.test.cpp19
3 files changed, 48 insertions, 2 deletions
diff --git a/include/mbgl/actor/scheduler.hpp b/include/mbgl/actor/scheduler.hpp
index bb2cf124b8..1115328797 100644
--- a/include/mbgl/actor/scheduler.hpp
+++ b/include/mbgl/actor/scheduler.hpp
@@ -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
diff --git a/src/mbgl/util/thread_pool.hpp b/src/mbgl/util/thread_pool.hpp
index 7642f9b4ca..e39c1abc73 100644
--- a/src/mbgl/util/thread_pool.hpp
+++ b/src/mbgl/util/thread_pool.hpp
@@ -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
diff --git a/test/util/async_task.test.cpp b/test/util/async_task.test.cpp
index 682926a17d..214e490fd8 100644
--- a/test/util/async_task.test.cpp
+++ b/test/util/async_task.test.cpp
@@ -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();
+} \ No newline at end of file