diff options
author | Mikhail Pozdnyakov <mikhail.pozdnyakov@mapbox.com> | 2019-10-28 17:12:58 +0200 |
---|---|---|
committer | Mikhail Pozdnyakov <mikhail.pozdnyakov@mapbox.com> | 2019-11-05 11:45:38 +0200 |
commit | 31421f8448d0192d04b95e31a0aecde2675b5988 (patch) | |
tree | 6fa71a14f10728e49997d8581e00929bce59c414 | |
parent | d8b1b2bacf0dd9812d62077a825067441037791b (diff) | |
download | qtlocation-mapboxgl-31421f8448d0192d04b95e31a0aecde2675b5988.tar.gz |
[core] Add Scheduler::scheduleAndReplyValue() API
-rw-r--r-- | include/mbgl/actor/scheduler.hpp | 27 | ||||
-rw-r--r-- | src/mbgl/util/thread_pool.hpp | 4 | ||||
-rw-r--r-- | test/util/async_task.test.cpp | 19 |
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 |